【版权声明:转载请保留出处:blog.csdn.net/gentleliu。邮箱:shallnew*163.com】
网卡驱动为每一个新的接口在一个全局的网络设备列表里插入一个数据结构.每一个接口由一个结构 net_device 项来描写叙述, 它在 <linux/netdevice.h> 里定义。该结构必须动态分配。
进行这样的分配的内核函数是 alloc_netdev, 它有下列原型:struct net_device *alloc_netdev(int sizeof_priv, const char *name, void (*setup)(struct net_device *));sizeof_priv 是驱动的的"私有数据"区的大小;name 是这个接口的名子;这个名子能够有一个 printf 风格的 %d 在里面. 内核用下一个可用的接口号来替换这个 %d。setup 是一个初始化函数的指针, 被调用来设置 net_device 结构的剩余部分。
struct net_device *alloc_etherdev(int sizeof_priv);当中sizeof_priv 是驱动的的"私有数据"区的大小;这个函数分配一个网络设备使用 eth%d 作为參数 name. 它提供了自己的初始化函数 ( ether_setup )来设置几个 net_device 字段, 使用对以太网设备合适的值。 因此, 没有驱动提供的初始化函数给 alloc_etherdev;
/** * ether_setup - setup Ethernet network device * @dev: network device * Fill in the fields of the device structure with Ethernet-generic values. */ void ether_setup(struct net_device *dev) { dev->header_ops = e_header_ops; dev->type = ARPHRD_ETHER; dev->hard_header_len = ETH_HLEN; dev->mtu = ETH_DATA_LEN; dev->addr_len = ETH_ALEN; dev->tx_queue_len = 1000; /* Ethernet wants good queues */ dev->flags = IFF_BROADCAST|IFF_MULTICAST; memset(dev->broadcast, 0xFF, ETH_ALEN); }
{ ether_setup(dev); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) dev->netdev_ops = &xxx_netdev_ops; #else dev->open = xxx_open; dev->stop = xxx_stop; dev->hard_start_xmit = xxx_tx; dev->get_stats = xxx_stats; // dev->change_mtu = xxx_change_mtu; ... #endif }假设使用alloc_etherdev函数分配,那么在该函数之后还须要作例如以下设置:
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) dev->netdev_ops = &xxx_netdev_ops; #else dev->open = xxx_open; dev->stop = xxx_stop; dev->hard_start_xmit = xxx_tx; dev->get_stats = xxx_stats; // dev->change_mtu = xxx_change_mtu; ... #endif事实上二者的区别就是alloc_etherdev函数默认自己主动调用ether_setup函数而且自己主动分配一个网络设备使用 eth%d 作为參数 name,而函数alloc_netdev须要自己传入參数来设置这些项而已。
linux内核数据包转发流程(一):网络设备驱动,布布扣,bubuko.com
原文:http://www.cnblogs.com/hrhguanli/p/3786389.html