在注册网络设备时,会调用pci_driver->probe函数,以e100网卡驱动为例,其最终会调用alloc_netdev_mqs来分配内存,并且在分配内存后调用setup函数(以太网为ether_setup)初始化二层地址等信息。下面以e100为例,分析alloc_netdev_mqs函数和ether_setup函数的执行流程;

相关函数的调用关系,如下;

 /**
* e100分配net_device,并对以太网信息进行初始化的函数调用关系
*
* e100_probe-->alloc_etherdev-->alloc_netdev_mqs
* |-->ether_setup                                                                                            
*/

分配函数最终会调用alloc_netdev_mqs来对net_device进行分配,并做相关成员的初始化;

 /**
* alloc_netdev_mqs - allocate network device
* @sizeof_priv: size of private data to allocate space for
* @name: device name format string
* @name_assign_type: origin of device name
* @setup: callback to initialize device
* @txqs: the number of TX subqueues to allocate
* @rxqs: the number of RX subqueues to allocate
*
* Allocates a struct net_device with private data area for driver use
* and performs basic initialization. Also allocates subqueue structs
* for each queue on the device.
*/
struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
unsigned char name_assign_type,
void (*setup)(struct net_device *),
unsigned int txqs, unsigned int rxqs)
{
struct net_device *dev;
size_t alloc_size;
struct net_device *p; BUG_ON(strlen(name) >= sizeof(dev->name)); /* 检查发送队列数 */
if (txqs < ) {
pr_err("alloc_netdev: Unable to allocate device with zero queues\n");
return NULL;
} /* 检查接收队列数 */
#ifdef CONFIG_SYSFS
if (rxqs < ) {
pr_err("alloc_netdev: Unable to allocate device with zero RX queues\n");
return NULL;
}
#endif /* 计算net_device结构大小 */
alloc_size = sizeof(struct net_device);
/* 加上私有数据大小 */
if (sizeof_priv) {
/* ensure 32-byte alignment of private area */
alloc_size = ALIGN(alloc_size, NETDEV_ALIGN);
alloc_size += sizeof_priv;
}
/* ensure 32-byte alignment of whole construct */
/* 整个空间做对齐后的大小 */
alloc_size += NETDEV_ALIGN - ; /* 分配内存 */
p = kvzalloc(alloc_size, GFP_KERNEL | __GFP_REPEAT);
if (!p)
return NULL; /* 内存对齐 */
dev = PTR_ALIGN(p, NETDEV_ALIGN); /* 计算对齐的填充 */
dev->padded = (char *)dev - (char *)p; /* 分配设备引用 */
dev->pcpu_refcnt = alloc_percpu(int);
if (!dev->pcpu_refcnt)
goto free_dev; /* 地址列表初始化 */
if (dev_addr_init(dev))
goto free_pcpu; /* 组播列表初始化 */
dev_mc_init(dev); /* 单播列表初始化 */
dev_uc_init(dev); /* 设置net */
dev_net_set(dev, &init_net); /* GSO设置 */
dev->gso_max_size = GSO_MAX_SIZE;
dev->gso_max_segs = GSO_MAX_SEGS; /* 初始化各种链表 */
INIT_LIST_HEAD(&dev->napi_list);
INIT_LIST_HEAD(&dev->unreg_list);
INIT_LIST_HEAD(&dev->close_list);
INIT_LIST_HEAD(&dev->link_watch_list);
INIT_LIST_HEAD(&dev->adj_list.upper);
INIT_LIST_HEAD(&dev->adj_list.lower);
INIT_LIST_HEAD(&dev->ptype_all);
INIT_LIST_HEAD(&dev->ptype_specific);
#ifdef CONFIG_NET_SCHED
hash_init(dev->qdisc_hash);
#endif
dev->priv_flags = IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM; /* 初始化设备硬件地址,mtu等参数 */
<span style="color: #ff0000;">setup(dev);</span> /* 队列长度为0,则采用默认值 */
if (!dev->tx_queue_len) {
dev->priv_flags |= IFF_NO_QUEUE;
dev->tx_queue_len = DEFAULT_TX_QUEUE_LEN;
} /* 设置发送队列数 */
dev->num_tx_queues = txqs;
dev->real_num_tx_queues = txqs; /* 分配初始化发送队列 */
if (netif_alloc_netdev_queues(dev))
goto free_all; #ifdef CONFIG_SYSFS
/* 设置接收队列数 */
dev->num_rx_queues = rxqs;
dev->real_num_rx_queues = rxqs; /* 分配初始化接收队列 */
if (netif_alloc_rx_queues(dev))
goto free_all;
#endif /* 拷贝名字 */
strcpy(dev->name, name); /* 赋值名字赋值类型 */
dev->name_assign_type = name_assign_type; /* 设置设备组 */
dev->group = INIT_NETDEV_GROUP; /* 设置默认ethtool操作 */
if (!dev->ethtool_ops)
dev->ethtool_ops = &default_ethtool_ops; /* 初始化netfilter入口 */
nf_hook_ingress_init(dev); return dev; free_all:
free_netdev(dev);
return NULL; free_pcpu:
free_percpu(dev->pcpu_refcnt);
free_dev:
netdev_freemem(dev);
return NULL;
}

如果二层设备遵循以太网规范,则上面setup函数实际会调用ether_setup,函数中对相关字段以太网标准进行了初始化,比类型,头部长度和操作,MTU,队列长度,标记等;前面文章中分析net_device结构时,其中的头部操作header_ops就是在这里进行赋值的,以太网对应的就是的eth_header_ops操作了;

 /**
* 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 = &eth_header_ops;
dev->type = ARPHRD_ETHER;
dev->hard_header_len = ETH_HLEN;
dev->min_header_len = ETH_HLEN;
dev->mtu = ETH_DATA_LEN;
dev->min_mtu = ETH_MIN_MTU;
dev->max_mtu = ETH_DATA_LEN;
dev->addr_len = ETH_ALEN;
dev->tx_queue_len = DEFAULT_TX_QUEUE_LEN;
dev->flags = IFF_BROADCAST|IFF_MULTICAST;
dev->priv_flags |= IFF_TX_SKB_SHARING; eth_broadcast_addr(dev->broadcast); }

网络设备之分配net_device结构的更多相关文章

  1. 网络驱动移植之net_device结构体及其相关的操作函数

    内核源码:Linux-2.6.38.8.tar.bz2 在Linux系统中,网络设备都被抽象为struct net_device结构体.它是网络设备硬件与上层协议之间联系的接口,了解它对编写网络驱动程 ...

  2. 网络驱动之net_device结构体

    在Linux系统中,网络设备都被抽象为struct net_device结构体.它是网络设备硬件与上层协议之间联系的接口,了解它对编写网络驱动程序非常有益,所以本文将着手简要介绍linux-2.6.3 ...

  3. 网络设备之net_device结构与操作

    net_device结构是一个很大的结构,其中包含了硬件信息,接口信息,其他辅助信息,以及设备操作函数等: 目前仍在读代码中,后续字段注释会逐渐补充: /** * struct net_device ...

  4. net_device 结构体分析

    /* * The DEVICE structure. * Actually, this whole structure is a big mistake. It mixes I/O * data wi ...

  5. struct net_device网络设备结构体详解

    转自:http://blog.csdn.net/viewsky11/article/details/53046787 在linux中使用struct net_device结构体来描述每一个网络设备.同 ...

  6. Linux kernel中网络设备的管理

    kernel中使用net_device结构来描述网络设备,这个结构是网络驱动及接口层中最重要的结构.该结构不仅描述了接口方面的信息,还包括硬件信息,致使该结构很大很复杂.通过这个结构,内核在底层的网络 ...

  7. Linux网络设备驱动架構學習(二)

    Linux网络设备驱动架構學習(二) 接下來會從以下幾個方面介紹網絡設備驅動的編寫流程: 1.網絡設備的註冊與註銷 2.網絡設備的初始化 3.網絡設備的打開與釋放 4.網絡數據發送流程 5.網絡數據接 ...

  8. 《linux设备驱动开发详解》笔记——14 linux网络设备驱动

    14.1 网络设备驱动结构 网络协议接口层:硬件无关,标准收发函数dev_queue_xmit()和netif_rx();  注意,netif_rx是将接收到的数据给上层,有时也在驱动收到数据以后调用 ...

  9. Linux 网络设备驱动程序设计(2)

    二.回环网卡的程序设计 /*************************** *******回环网卡的驱动程序*** ***********吕晓宁*********** *********2015 ...

随机推荐

  1. Microsoft Edge goes Chromium

    Microsoft Edge goes Chromium https://techcrunch.com/2018/12/06/microsoft-edge-goes-chromium-and-maco ...

  2. [OS] 生产者-消费者问题(有限缓冲问题)

    ·最简单的情形--(一个生产者 + 一个消费者 + 一个大小为1的有限缓冲) 首先来分析其中的同步关系: ·必须在生产者放入一个产品之后,消费者才能够从缓冲中取出产品来消费.·只有在消费者从缓冲区中取 ...

  3. 【bzoj4842】[Neerc2016]Delight for a Cat 线性规划与网络流

    题目描述 $n$ 个连续的位置,每个位置可以填入 S 和 E ,第 $i$ 个位置填入 S 可以获得 $s_i$ 的收益,填入 E 可以获得 $e_i$ 的收益.要求每连续的 $k$ 个位置必须包含至 ...

  4. [BZOJ2821]作诗

    description 在线询问区间内出现次数为正偶数的数的种数. data range \[n,m\le 10^5\] solution 分块大法好 首先离散化权值 这种对于权值做询问并且询问放在一 ...

  5. YY的GCD 莫比乌斯反演

    ---题面--- 题解: $ans = \sum_{x = 1}^{n}\sum_{y = 1}^{m}\sum_{i = 1}^{k}[gcd(x, y) == p_{i}]$其中k为质数个数 $$ ...

  6. BZOJ3339:Rmq Problem & BZOJ3585 & 洛谷4137:mex——题解

    前者:https://www.lydsy.com/JudgeOnline/problem.php?id=3339 后者: https://www.lydsy.com/JudgeOnline/probl ...

  7. BZOJ2653:middle——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=2653 Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2], ...

  8. Mac安装mysqldb

    一. 安装mysql (一)下载地址 https://pan.baidu.com/s/1slw50LZ 安装成功后,在系统偏好设置里有MySQL图标,可以启动或关闭MySQL 二. Mysql roo ...

  9. [学习笔记]FFT——快速傅里叶变换

    大力推荐博客: 傅里叶变换(FFT)学习笔记 一.多项式乘法: 我们要明白的是: FFT利用分治,处理多项式乘法,达到O(nlogn)的复杂度.(虽然常数大) FFT=DFT+IDFT DFT: 本质 ...

  10. Cydia Substrate based DexDumper's weakness

    得益于Cydia Substrate框架,HOOK Native函数变得简单,也给脱壳带来方便. 像ijiami免费版,360,classes.dex被加密到so文件并运行时释放到内存,因此针对相关函 ...