转载:http://blog.csdn.net/freas_1990/article/details/9238183

看了一些linux网卡驱动的处理技术,对有些概念还是无法理解,突然搜到这篇文章,挺有意思的,有些启发,以后我也要尝试用这种方式写文章

Jack:Linux外部设备的性能如何才能高呢?

我:你为什么希望外部设备的性能好呢?

Jack:典型的说,外部设备如磁盘、网卡都需要非常好的性能。磁盘设备处理性能好,才能承载数据库系统。网卡性能好,才能承载高性能server(数据库或者web server)。

我:那你觉得用什么样的方式处理这两个外部设备,它的性能会好呢?

Jack:外部设备要好,当然应该采用中断方式,这是性能最高的。

我:你错了。外部设备与CPU的交互方式,最快的是DMA。但是,DMA方式会使外部设备的控制器独占PCI总线,从而CPU无法与外部设备进行交互——这对通用型操作系统来说,是很难接受的。所以DMA方式,在Linux内核里使用得很少。Linux笔记是一个通用型操作系统,而非专用型嵌入式操作系统。

Jack:说了这么多,还是要用中断才行。

我:是的。但是中断仅仅是最基本的方式。使用中断这种外部设备处理方式,有两个硬伤需要面对:

1、丢失中断问题:在中断响应代码里,一般都会调用cli()宏定义关闭中断,当中断完成之后,再调用sti()宏定义打开中断。如果中断响应代码执行时间比较长(毫秒级别),那么在这段时间内,中断都无法响应——这对于一个server操作系统来说,是无法接受的。

2、SMP均衡问题:在SMP下,常用的中断默认只会落到CPU0上去,其余的CPU无法处理中断,这对整个操作系统的可扩展性来说,是致命的。

这两个问题对所有外部设备都适用,如果外部设备对性能要求非常之高,那么,这两个问题一定要解决。

Jack:常见的对性能要求非常之高的外部设备有哪些呢?

我:最常见的是网卡设备和磁盘设备。其中,对于网卡设备而言,这两个问题尤其棘手。

Jack:对于网卡设备而言,这两个问题是怎么解决的呢?

我:对于中断丢失的问题,Linux内核早期采用了BH的机制。而对于SMP的问题,Linux内核至今没有完美的解决办法。当然,这并不是说就没有解决的办法,只是有些互联网公司没把核心技术开源出来而已。

Jack:BH机制是怎么回事呢?

我:BH是bottom half的缩写,但是BH已经是一个专有名词,代表最早的Linux内核的bottom half机制,而bottom half是一个通用名词。Linux内核从程序猿的角度把中断响应程序分为两部分——上半部、下半部。上半部做标记功能用,下半部根据上半部的标记干活。上半部与下半部的本质区别是,上半部可以关闭中断,而下半部不能关闭中断。所以,bottom half的概念,完全是hacker意淫出来的,并非是CPU层面的概念。

Jack:那BH这种意淫出来的机制的好处在哪里呢?

我:这种机制的优点在于解决了第一个问题——丢失中断。通过把上半部极致地浓缩,可以最大限度地减少关闭中断的时间,从而减少中断丢失——没有绝对的不丢失中断,只能最大限度地减少中断丢失。

Jack:那BH机制的缺点是什么呢?

我:这个问题问得很好,不仅问了有点是什么,同时问了缺点是什么。两个点你都弄清楚了,差不多就高潮了。

Jack:去死吧。

我:BH机制的缺点在于无法解决第二个问题。就是BH机制在SMP下,表现得太龊逼了。

Jack:仔细一点呢?

我:BH硬编码定义了32类Bottom half,这32类botton half在同一时刻只能执行其中一种,即便是在SMP环境下,也是如此。所以,BH机制是绝对的串行化,而没有任何并发能力。

Jack:绝对的串行化也很好,实现非常简单,只是无法发挥多核的优势。

我:这种说法等于上馆子吃饭只喝水不点菜、不叫饭,因为这样省钱。但是这样的做法,是SB的。

Jack:那么Linux在处理外部设备的性能问题上,如何解决SMP的呢?

我:在Linux2.6版本内核里,提供了3种成熟的方法来解决外设与SMP配合的问题:软中断、tasklet、工作队列。其中,软中断是一种全新的机制,具备在SMP下软中断类型间的并发甚至是同种软中断内的并发能力。tasklet建立在软中断之上,是软中断的一种特例,相比于软中断,tasklet不具备同种软中断内的并发能力。对于除磁盘设备、网卡设备而言,几乎所有的外部设备用tasklet就够了。只有极少数的外部设备需要自己定制软中断。当然了,软中断的定制不是那么简单的。且不说需要对软中断的原理、实现代码非常熟悉。更难的是,需要自己实现软中断在SMP下,同种软中断内部间的互斥与同步。如果采用简单粗暴的spinlock,那么软中断在性能上就已经失去意义。而采用别的数据结构实现数据同步与互斥,又具备相当大的难度,所以,即便是Linux内核的官方版本,对这个问题也是极为头疼。至于第三种——工作队列。这种机制与前两种机制的最大差别在于,这种机制的bottom half会通过内核线程进入休眠,之后被唤醒。这里有两个难点,第一点是,休眠会引起上下文切换(context switch),对性能具有极大的杀伤。第二点是,Linux内核作者是非常反对user创建内核线程的——原因不言而喻,Linux内核是内核作者写好对外提供服务的,你一来就动大手术,把内核改造了,加了线程,谁能保证在某种情况下不出现问题呢?出了问题之后,会找谁解决呢?一般人当然首先先到内核作者。可是,当你找到内核作者的时候,情形好比是你把一台刚买的笔记本用螺丝刀打开过了,还下了几个零件,然后电脑坏了,你对售后服务说“我的电脑坏了,你帮我修理下。”

软中断网卡处理&Linux高性能外部设备处理机制&SMP的更多相关文章

  1. linux 中断底半部机制对比(任务队列,工作队列,软中断)--由linux RS485引出的血案【转】

    转自:http://blog.chinaunix.net/uid-20768928-id-5077401.html 在LINUX RS485的使用过程中,由于各种原因,最后不得不使用中断底半部机制的方 ...

  2. Linux 高性能服务器编程——IP协议详解

    1 IP服务特点 IP协议是TCP/IP协议族的动力,它为上层协议提供无状态.无连接.不可靠的服务. 无状态:IP通信双方不同步传输数据的状态信息,因此IP数据包的发送.传输和接收都是无序的.     ...

  3. linux下epoll实现机制

    linux下epoll实现机制 原作者:陶辉 链接:http://blog.csdn.net/russell_tao/article/details/7160071 先简单回顾下如何使用C库封装的se ...

  4. Linux内核态抢占机制分析(转)

    Linux内核态抢占机制分析  http://blog.sina.com.cn/s/blog_502c8cc401012pxj.html 摘 要]本文首先介绍非抢占式内核(Non-Preemptive ...

  5. Linux 高性能服务器编程——多线程编程

    问题聚焦:     在简单地介绍线程的基本知识之后,主要讨论三个方面的内容:    1 创建线程和结束线程:    2 读取和设置线程属性:    3 线程同步方式:POSIX信号量,互斥锁和条件变量 ...

  6. Linux 高性能服务器编程——高性能服务器程序框架

    问题聚焦:     核心章节.     服务器一般分为如下三个主要模块:I/O处理单元(四种I/O模型,两种高效事件处理模块),逻辑单元(两种高效并发模式,有效状态机)和存储单元(不讨论). 服务器模 ...

  7. Linux 高性能服务器编程——TCP协议详解

    问题聚焦:     本节从如下四个方面讨论TCP协议:     TCP头部信息:指定通信的源端端口号.目的端端口号.管理TCP连接,控制两个方向的数据流     TCP状态转移过程:TCP连接的任意一 ...

  8. Linux 高性能服务器编程——TCP/IP协议族

    1 TCP/IP协议族体系结构 数据链路层:     职责:实现网卡接口的网络驱动程序,一处理数据在物理媒介(如以太网.令牌环等)上的传输.     常用协议:ARP协议(地址解析协议),RARP协议 ...

  9. Linux内核抢占实现机制分析【转】

    Linux内核抢占实现机制分析 转自:http://blog.chinaunix.net/uid-24227137-id-3050754.html [摘要]本文详解了Linux内核抢占实现机制.首先介 ...

随机推荐

  1. https://www.cnblogs.com/gaoxiang12/p/3695962.html

    https://www.cnblogs.com/gaoxiang12/p/3695962.html

  2. python——获取数据类型

    在python中,可使用type()和isinstance()内置函数获取数据类型 如: (1)type()的使用方法: >>> a = '230'         >> ...

  3. POJ:2449-Remmarguts' Date(单源第K短路)

    Remmarguts' Date Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 33081 Accepted: 8993 Des ...

  4. html+css调用服务器端字体

    在浏览网页时,由于客户端没有安装某些特殊字体,导致网页文字无法按设计正常显示,这时我们可以使用服务器字体来避免这种现象的发送 语法 @font-face { /* 自定义字体名称 */ font-fa ...

  5. 8 实现10mins用户登录与注册

    1.重新认识登录 2.实现登录功能 (1)Django 自带的authenticate, login模块 from django.contrib.auth import authenticate, l ...

  6. curl 编译

    curl是利用URL语法在命令行方式下工作的开源文件传输工具.它被广泛应用在Unix.多种Linux发行版中,并且有DOS和Win32.Win64下的移植版本.支持很多协议:FTP, FTPS, HT ...

  7. 《数据结构》C++代码 线性表

    线性表,分数组和链表两种(官方名称记得是叫顺序存储和链式存储).代码里天天用,简单写写. 首先是数组,分静态.动态两种,没什么可说的,注意动态的要手动释放内存就好了. 其次是链表,依旧分静态.动态.课 ...

  8. Python爬虫教程

    Python爬虫(1):基本原理 Python爬虫(2):Requests的基本用法 Python爬虫(3):Requests的高级用法 Python爬虫(4):Beautiful Soup的常用方法 ...

  9. 六 APPIUM Android 定位方式

    文本转自:http://www.cnblogs.com/sundalian/p/5629500.html APPIUM Android 定位方式   1.定位元素应用元素 1.1通过id定位元素 An ...

  10. httpclient传参类型与响应参数接收

    https://blog.csdn.net/qq_26562641/article/details/72817457 https://blog.csdn.net/chenjf0221/article/ ...