从事linux C开发工作以来,工作内容主要是在应用层,对nginx和unbound等软件有些了解,也常对这2个软件进行二次开发。 对网络这块一直比较有兴趣。也很好奇网卡到底是怎么接受到报文的,以及报文如何被应用层所接受。自己在网上学习了一下,做个简单总结。 以飨后人。基本上我觉得分以下几个部分:

一、预备知识

1、PCI设备是有标准的,就是说PCI设备必须在固定位置包含公司、设备等信息,这样内核启动的时候读取出来,并保存在 struct pci_dev中。最终将所有PCI设备,组织成一个链表结构。

2、PCI标准中规定,PCI设备有一个配置区域,这些区域由BIOS在机器启动的时候,写入分配给该 PCI设备中断号,内存映射地址。因为由BIOS 统一分配,所有这些资源就不会重复。

二、网卡驱动初始过程

基本上了解内核模块怎么编写的人,应该了解rtl8139_init_module是在insmod命令模块加载的时候被调用的,它会调用pci_register_driver, 该函数是内核提供的,用来注册PCI设备驱动的。内核会遍历PCI设备链表,根据rtl8139_pci_tbl提供的信息,对比信息,如果满足,那么表明 这个驱动就是用来驱动这个设备的。一个设备只能有一个驱动,一个驱动可以驱动多个设备。

当给设备找到驱动以后,会调用pci_driver结构的 probe函数。也就是rtl8139_init_one函数。这个函数,就是会初始化设备,这块主要需要参考设备厂家的datasheet,操作各种寄存器。细节不讲了, 主要是让大家了解下大致,细节可以看一下代码。初始化的时候,dev->netdev_ops = &rtl8139_netdev_ops;,这就相当于注册了各种驱动处理函数了。 其中rtl8139_open在ifconfig eth0 up的时候会被调用,它会request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev);注册驱动。 dev-irq就是BIOS分配的。rtl8139_interrupt是中断处理函数。

三、网卡发送报文过程

发送的时候会调用 rtl8139_start_xmit。通过调用skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);,把报文写入ring buf, 也就是环形缓冲区,一般有4个。也就是说,发送的时候,就是把报文网ring buf中写,写满了就等下一次再发。

四、网卡接受报文过程

网上除了有发送缓冲区,也有接受缓冲区。当有报文来的时候,报文会被 DMA复制到缓冲区,然后发起中断。最终调用中断处理函数rtl8139_interrupt 他最终通过调用__napi_schedule(&tp->napi);把当前设备pool函数加入NAPI的链表中。也就rtl8139_poll函数。到目前为止,报文硬件中断处理就结束了。 那么肯定很好奇,报文还没被处理呢,只是放在缓冲区。其实就是通过中断下半部,也就是软中断soft irq来接受的。 下面继续:

软中断,算是一个内核进程,它没事处理的时候就挂起。它是可以被唤醒的。当它被唤醒的时候,它会执行net_rx_action,这个函数会遍历挂在 它上面的链表,也就是poll_list,也就是我们上面注册的rtl8139_poll。这个rtl8139_poll最终会调用rtl8139_rx来接受报文,而这个函数里面有个 while循环,就不停的从缓冲区中读取数据,并把数据填充到skb中,最终调用netif_receive_skb。来把报文往上送,这个函数呢,最终会根据不用的 协议调用相应的处理方法,如果是IP报文,最终会调用ip_rcv。之后,就会被送到应用层。具体的不是一下能讲完。后面有空再补充。

8139too.c网卡驱动简单分析的更多相关文章

  1. Linux网卡驱动架构分析

    一.网卡驱动架构 由上到下层次依次为:应用程序→系统调用接口→协议无关接口→网络协议栈→设备无关接口→设备驱动. 二.重要数据结构 1.Linux内核中每一个网卡由一个net_device结构来描述. ...

  2. DM9000网卡驱动深度分析

    一.dm9000_porbe函数分析 不同于u-boot代码,tq2440中的DM9000更加复杂,需要分析的点也很多: /* * Search DM9000 board, allocate spac ...

  3. [国嵌攻略][136][DM9000网卡驱动深度分析]

    网卡初始化 1.分配描述结构,alloc_etherdev 2.获取平台资源,platform_get_resource 2.1.在s3c_dm9k_resource中有相关的资源 2.2.add地址 ...

  4. LDD3 字符设备驱动简单分析

    最近在看LDD3,理解了一下,为了加深自己的印象,自己梳理一下.我用的CentOS release 6.6 (Final)系统. 一.编写编译内核模块的Makefile 以下是我用的Makefile ...

  5. Linux 网卡驱动设备程序设计(1)

    一.网卡驱动架构分析 1. Linux 网络子系统 #系统调用接口层 为应用程序提供访问网络子系统的统一方法. #协议无关层 提供通用的方法来使用传输层协议. #协议栈的实现 实现具体的网络协议 #设 ...

  6. Linux PCI网卡驱动的详细分析

    学习应该是一个先把问题简单化,在把问题复杂化的过程.一开始就着手处理复杂的问题,难免让人有心惊胆颤,捉襟见肘的感觉.读Linux网卡驱动也是一 样.那长长的源码夹杂着那些我们陌生的变量和符号,望而生畏 ...

  7. Linux网卡驱动移植--Dm9000网卡驱动分析

    1. Linux网络体系结构由以下5部分组成 ① 系统调用接口: 位于Linux网络子系统的顶部,为应用程序提供访问内核网络子系统的方法,主要指socket系统调用. ② 协议无关接口: 实现一组基于 ...

  8. 【Linux高级驱动】如何分析并移植网卡驱动

    dm9000的驱动分析 m9000_init platform_driver_register(); db); db); );  ; id_val ; id_val ; /* 获取芯片型号 */ id ...

  9. Xilinx Uboot网卡驱动分析

    1.MAC控制器.网卡.PHY.MDIO.mii.gmii.rgmii概念扫盲 网卡在功能上包含OSI模型的两个层,数据链路层和物理层.物理层定义了数据传送与接收所需要的电与光信号.线路状态.时钟基准 ...

随机推荐

  1. 关于history的Linux命令行

    1.使用 HISTTIMEFORMAT 显示时间戳当你从命令行执行 history 命令后,通常只会显示已执行命令的序号和命令本身.如果你想要查看命令历史的时间戳,那么可以执行: # export H ...

  2. 【转载】Linux 信号列表

    转自:http://blog.csdn.net/muge0913/article/details/7322710 信号及其简介 信号是一种进程通信的方法,他应用于异步事件的处理.信号的实现是一种软中断 ...

  3. JS base64 加密和 后台 base64解密(防止中文乱码)

    直接上代码 1,js(2个文件,网上找的)  不要觉的长,直接复制下来就OK //UnicodeAnsi.js文件 //把Unicode转成Ansi和把Ansi转换成Unicode function ...

  4. Android——Toast.makeText()

    1.Toast 作用 它是android中一种简单的消息提示框,它没有焦点(即不能被点击),会根据设置的时间自动消失. 2.介绍下Toast的参数 Toast t = Toast.makeText(M ...

  5. IOS网络第四天 -网络文件上传(0923略)

    01-NSURLSession02-断点续传 02-文件上传01-基本的上传 03-文件上传03-代码封装 04-文件上传04-获得MIMEType.mp4 05-文件的压缩和解压缩.mp4 06-压 ...

  6. shape

    <?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http:/ ...

  7. erlang ssl

    http://itindex.net/detail/50701-tomcat-bio-nio.apr http://blog.csdn.net/libing1991_/article/details/ ...

  8. C#中异常:“The type initializer to throw an exception(类型初始值设定项引发异常)”的简单分析与解决方法

    对于C#中异常:“The type initializer to throw an exception(类型初始值设定项引发异常)”的简单分析,目前本人分析两种情况,如下: 情况一: 借鉴麒麟.NET ...

  9. Redis数据类型介绍

    Redis 数据类型 Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合). String(字符串) st ...

  10. Java局部变量

    局部变量是在方法被执行时创建,在方法执行结束时被销毁.局部变量在使用时必须进行赋值操作或被初始化,否则会出现编译错误. 在相互不嵌套的作用域中可以同时声明两个名称,类型相同的局部变量, public ...