【版权声明:转载请保留出处: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 = ð_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需要自己传入参数来设置这些项而已。