⑴ 《linux内核探秘深入解析文件系统和设备驱动的架构与设计》epub下载在线阅读,求百度网盘云资源
《Linux内核探秘》(高剑林)电子书网盘下载免费在线阅读
资源链接:
链接:https://pan..com/s/1X0FBrzSSo0dOW1ZL0dGxqg
书名:Linux内核探秘
作者:高剑林
豆瓣评分:6.7
出版社:机械工业出版社
出版年份:2013-12-1
页数:232
内容简介:
《Linux内核探秘:深入解析文件系统和设备驱动的架构与设计》从工业需求角度出发,注重效率和实用性,是帮助内核研发及调试、驱动开发等领域工程师正确认识并高效利用Linux内核的难得佳作!作者是腾讯公司资深的Linux内核专家和存储系统专家,在该领域工作和研究的10余年间,面试了数百位Linux内核工程师,深知学习Linux内核过程中经常遇到的困惑,以及在工作中容易犯的错误。基于这些原因作者撰写了本书。本书出发点和写作方式可谓独辟蹊径,将Linux内核分为两个维度,一是基础部分和应用部分,二是内核架构和内核实现,将两个维有机统一,深入分析了Linux内核的文件系统、设备驱动的架构设计与实现原理。
《Linux内核探秘:深入解析文件系统和设备驱动的架构与设计》在逻辑上分为三部分:第一部分(第1~2章)首先将内核层划分为基础层和应用层,讲解了基础层包含的服务和数据结构,以及应用层包含的各种功能,然后对文件系统的架构进行了提纲挈领的介绍,为读者学习后面的知识打下基础;第二部分(第3~9章)从设备到总线到驱动,逐步深入,剖析了设备的总体架构、为设备服务的特殊文件系统sysfs、字符设备和input设备、platform总线、serio总线、PCI总线、块设备的实现原理和工作机制;第三部分(第10~13章)对文件系统的读写机制进行了深入分析,最后通过一个真实文件系统ext2,复习本书所有知识点。
作者简介:
高剑林,资深Linux内核专家、存储系统专家、嵌入式系统专家。先后就职于华为、UT斯达康、赛门铁克等公司,从事路由器设备研发、软件开发和存储系统研究相关的工作10余年,经验非常丰富。现就职于腾讯,负责存储系统的开发和研究。
⑵ 如何开始学习Linux内核
想要学好Linux,需要具备以下能力:
1. 基本功要扎实
学习任何一种语言,必备的基本功是必须要有的,一方面可以提高效率,另一方面可以拓宽思路。
对于Linux基本知识的学习,对一些初学者来说是枯燥乏味的,可以通过理解再背诵的方式先进行代码及语法的学习,然后进行实践操作,必须手动输入命令行,不要借助工具,这样可以更快速有效的掌握Linux。
2. 学以致用
Linux学习的目的是应用,Linux基本知识是一些零散的技术,当没有应用在项目上时,我们无法理解他的真实价值,所以打好基本功之后,最紧迫的是多做几个完整的项目,刚开始可以是功能简单的项目,之后可以选择稍微复杂的项目,勤于动手,敢于实践,一定能学好Linux。
3. 学会使用Linux联机帮助
任何一种教材都不会完全讲述Linux知识,一般讲的都是比较常用的或者是比较有代表性的知识,但是,我们在项目应用中往往有些功能的实现是需要一些生僻知识和技能的,那么,如何查找我们所需的知识呢,推荐查阅Linux帮助文档,主流的Linux都自带详细的帮助文档,很方便解决问题!
4. 在网上找资源
在Linux的学习和应用中,难免会遇到一些没有思路、不知道如何解决的问题,这时就要借助网络力量,可以通过搜索引擎搜索查找,也可以咨询资深技术人员,最终实现问题的解决,这是Linux知识积累的一个重要的途径!
5. 查阅英文技术文档
如果想深入学习Linux,查阅英文技术文档是十分必要的,往往最新的技术都是采用英文文档的方式发布的,而且更全面,因此,对于Linux人员来说,多看一些Linux技术文档,对于掌握前沿技术和加深知识是十分有必要的!
⑶ 《Linux内核探秘深入解析文件系统》pdf下载在线阅读全文,求百度网盘云资源
《Linux内核探秘深入解析文件系统》网络网盘pdf最新全集下载:
链接: https://pan..com/s/10_gfLOVNEpy-TAzONQ0pvA
⑷ linux内核同步问题
Linux内核设计与实现 十、内核同步方法
手把手教Linux驱动5-自旋锁、信号量、互斥体概述
== 基础概念: ==
并发 :多个执行单元同时进行或多个执行单元微观串行执行,宏观并行执行
竞态 :并发的执行单元对共享资源(硬件资源和软件上的全局变量)的访问而导致的竟态状态。
临界资源 :多个进程访问的资源
临界区 :多个进程访问的代码段
== 并发场合: ==
1、单CPU之间进程间的并发 :时间片轮转,调度进程。 A进程访问打印机,时间片用完,OS调度B进程访问打印机。
2、单cpu上进程和中断之间并发 :CPU必须停止当前进程的执行中断;
3、多cpu之间
4、单CPU上中断之间的并发
== 使用偏向: ==
==信号量用于进程之间的同步,进程在信号量保护的临界区代码里面是可以睡眠的(需要进行进程调度),这是与自旋锁最大的区别。==
信号量又称为信号灯,它是用来协调不同进程间的数据对象的,而最主要的应用是共享内存方式的进程间通信。本质上,信号量是一个计数器,它用来记录对某个资源(如共享内存)的存取状况。它负责协调各个进程,以保证他们能够正确、合理的使用公共资源。它和spin lock最大的不同之处就是:无法获取信号量的进程可以睡眠,因此会导致系统调度。
1、==用于进程与进程之间的同步==
2、==允许多个进程进入临界区代码执行,临界区代码允许睡眠;==
3、信号量本质是==基于调度器的==,在UP和SMP下没有区别;进程获取不到信号量将陷入休眠,并让出CPU;
4、不支持进程和中断之间的同步
5、==进程调度也是会消耗系统资源的,如果一个int型共享变量就需要使用信号量,将极大的浪费系统资源==
6、信号量可以用于多个线程,用于资源的计数(有多种状态)
==信号量加锁以及解锁过程:==
sema_init(&sp->dead_sem, 0); / 初始化 /
down(&sema);
临界区代码
up(&sema);
==信号量定义:==
==信号量初始化:==
==dowm函数实现:==
==up函数实现:==
信号量一般可以用来标记可用资源的个数。
举2个生活中的例子:
==dowm函数实现原理解析:==
(1)down
判断sem->count是否 > 0,大于0则说明系统资源够用,分配一个给该进程,否则进入__down(sem);
(2)__down
调用__down_common(sem, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);其中TASK_UNINTERRUPTIBLE=2代表进入睡眠,且不可以打断;MAX_SCHEDULE_TIMEOUT休眠最长LONG_MAX时间;
(3)list_add_tail(&waiter.list, &sem->wait_list);
把当前进程加入到sem->wait_list中;
(3)先解锁后加锁;
进入__down_common前已经加锁了,先把解锁,调用schele_timeout(timeout),当waiter.up=1后跳出for循环;退出函数之前再加锁;
Linux内核ARM构架中原子变量的底层实现研究
rk3288 原子操作和原子位操作
原子变量适用于只共享一个int型变量;
1、原子操作是指不被打断的操作,即它是最小的执行单位。
2、最简单的原子操作就是一条条的汇编指令(不包括一些伪指令,伪指令会被汇编器解释成多条汇编指令)
==常见函数:==
==以atomic_inc为例介绍实现过程==
在Linux内核文件archarmincludeasmatomic.h中。 执行atomic_read、atomic_set这些操作都只需要一条汇编指令,所以它们本身就是不可打断的。 需要特别研究的是atomic_inc、atomic_dec这类读出、修改、写回的函数。
所以atomic_add的原型是下面这个宏:
atomic_add等效于:
result(%0) tmp(%1) (v->counter)(%2) (&v->counter)(%3) i(%4)
注意:根据内联汇编的语法,result、tmp、&v->counter对应的数据都放在了寄存器中操作。如果出现上下文切换,切换机制会做寄存器上下文保护。
(1)ldrex %0, [%3]
意思是将&v->counter指向的数据放入result中,并且(分别在Local monitor和Global monitor中)设置独占标志。
(2)add %0, %0, %4
result = result + i
(3)strex %1, %0, [%3]
意思是将result保存到&v->counter指向的内存中, 此时 Exclusive monitors会发挥作用,将保存是否成功的标志放入tmp中。
(4) teq %1, #0
测试strex是否成功(tmp == 0 ??)
(5)bne 1b
如果发现strex失败,从(1)再次执行。
Spinlock 是内核中提供的一种比较常见的锁机制,==自旋锁是“原地等待”的方式解决资源冲突的==,即,一个线程获取了一个自旋锁后,另外一个线程期望获取该自旋锁,获取不到,只能够原地“打转”(忙等待)。由于自旋锁的这个忙等待的特性,注定了它使用场景上的限制 —— 自旋锁不应该被长时间的持有(消耗 CPU 资源),一般应用在==中断上下文==。
1、spinlock是一种死等机制
2、信号量可以允许多个执行单元进入,spinlock不行,一次只能允许一个执行单元获取锁,并且进入临界区,其他执行单元都是在门口不断的死等
3、由于不休眠,因此spinlock可以应用在中断上下文中;
4、由于spinlock死等的特性,因此临界区执行代码尽可能的短;
==spinlock加锁以及解锁过程:==
spin_lock(&devices_lock);
临界区代码
spin_unlock(&devices_lock);
==spinlock初始化==
==进程和进程之间同步==
==本地软中断之间同步==
==本地硬中断之间同步==
==本地硬中断之间同步并且保存本地中断状态==
==尝试获取锁==
== arch_spinlock_t结构体定义如下: ==
== arch_spin_lock的实现如下: ==
lockval(%0) newval(%1) tmp(%2) &lock->slock(%3) 1 << TICKET_SHIFT(%4)
(1)ldrex %0, [%3]
把lock->slock的值赋值给lockval;并且(分别在Local monitor和Global monitor中)设置独占标志。
(2)add %1, %0, %4
newval =lockval +(1<<16); 相当于next+1;
(3)strex %2, %1, [%3]
newval =lockval +(1<<16); 相当于next+1;
意思是将newval保存到 &lock->slock指向的内存中, 此时 Exclusive monitors会发挥作用,将保存是否成功的标志放入tmp中。
(4) teq %2, #0
测试strex是否成功
(5)bne 1b
如果发现strex失败,从(1)再次执行。
通过上面的分析,可知关键在于strex的操作是否成功的判断上。而这个就归功于ARM的Exclusive monitors和ldrex/strex指令的机制。
(6)while (lockval.tickets.next != lockval.tickets.owner)
如何lockval.tickets的next和owner是否相等。相同则跳出while循环,否则在循环内等待判断;
* (7)wfe()和smp_mb() 最终调用#define barrier() asm volatile ("": : :"memory") *
阻止编译器重排,保证编译程序时在优化屏障之前的指令不会在优化屏障之后执行。
== arch_spin_unlock的实现如下: ==
退出锁时:tickets.owner++
== 出现死锁的情况: ==
1、拥有自旋锁的进程A在内核态阻塞了,内核调度B进程,碰巧B进程也要获得自旋锁,此时B只能自旋转。 而此时抢占已经关闭,(单核)不会调度A进程了,B永远自旋,产生死锁。
2、进程A拥有自旋锁,中断到来,CPU执行中断函数,中断处理函数,中断处理函数需要获得自旋锁,访问共享资源,此时无法获得锁,只能自旋,产生死锁。
== 如何避免死锁: ==
1、如果中断处理函数中也要获得自旋锁,那么驱动程序需要在拥有自旋锁时禁止中断;
2、自旋锁必须在可能的最短时间内拥有
3、避免某个获得锁的函数调用其他同样试图获取这个锁的函数,否则代码就会死锁;不论是信号量还是自旋锁,都不允许锁拥有者第二次获得这个锁,如果试图这么做,系统将挂起;
4、锁的顺序规则(a) 按同样的顺序获得锁;b) 如果必须获得一个局部锁和一个属于内核更中心位置的锁,则应该首先获取自己的局部锁 ;c) 如果我们拥有信号量和自旋锁的组合,则必须首先获得信号量;在拥有自旋锁时调用down(可导致休眠)是个严重的错误的;)
== rw(read/write)spinlock: ==
加锁逻辑:
1、假设临界区内没有任何的thread,这个时候任何的读线程和写线程都可以键入
2、假设临界区内有一个读线程,这时候信赖的read线程可以任意进入,但是写线程不能进入;
3、假设临界区有一个写线程,这时候任何的读、写线程都不可以进入;
4、假设临界区内有一个或者多个读线程,写线程不可以进入临界区,但是写线程也无法阻止后续的读线程继续进去,要等到临界区所有的读线程都结束了,才可以进入,可见:==rw(read/write)spinlock更加有利于读线程;==
== seqlock(顺序锁): ==
加锁逻辑:
1、假设临界区内没有任何的thread,这个时候任何的读线程和写线程都可以键入
2、假设临界区内没有写线程的情况下,read线程可以任意进入;
3、假设临界区有一个写线程,这时候任何的读、写线程都不可以进入;
4、假设临界区内只有read线程的情况下,写线程可以理解执行,不会等待,可见:==seqlock(顺序锁)更加有利于写线程;==
读写速度 : CPU > 一级缓存 > 二级缓存 > 内存 ,因此某一个CPU0的lock修改了,其他的CPU的lock就会失效;那么其他CPU就会依次去L1 L2和主存中读取lock值,一旦其他CPU去读取了主存,就存在系统性能降低的风险;
mutex用于互斥操作。
互斥体只能用于一个线程,资源只有两种状态(占用或者空闲)
1、mutex的语义相对于信号量要简单轻便一些,在锁争用激烈的测试场景下,mutex比信号量执行速度更快,可扩展
性更好,
2、另外mutex数据结构的定义比信号量小;、
3、同一时刻只有一个线程可以持有mutex
4、不允许递归地加锁和解锁
5、当进程持有mutex时,进程不可以退出。
• mutex必须使用官方API来初始化。
• mutex可以睡眠,所以不允许在中断处理程序或者中断下半部中使用,例如tasklet、定时器等
==常见操作:==
struct mutex mutex_1;
mutex_init(&mutex_1);
mutex_lock(&mutex_1)
临界区代码;
mutex_unlock(&mutex_1)
==常见函数:==
=
⑸ 介绍Linux内核的书求推荐
第一:《Linux内核设计与实现》
简称LKD,从入门开始,介绍了诸如进程管理、系统调用、中断和中断处理程序、内核同步、时间管理、内存管理、地址空间、调试技术等方面,内容比较浅显易懂,个人认为是内核新人首先必读的书籍。新人得有此书,足矣!
第二:《深入理解Linux内核》
简称ULK,相比于LKD的内容不够深入、覆盖面不广,ULK要深入全面得多。
前面这两本,一本提纲挈领,一本全面深入。
第三:《Linux设备驱动程序》
简称LDD,驱动开发者都要人手一本了。
第四:《深入理解Linux虚拟内存管理》
简称LVMM,是一本介绍Linux虚拟内存管理机制的书。如果你希望深入的研究Linux的内存管理子系统,仔细的研读这本书无疑是最好的选择。
第五:《深入理解LINUX网络内幕》
一本讲解网络子系统实现的书,通过这本书,我们可以了解到Linux内核是如何实现复杂的网络功能的。
了解更多开源相关,去LUPA社区看看吧。
⑹ Linux内核设计与实现 深入理解linux内核 哪个好
都是好书啊,我都有,linux内核设计比较理论,讲述操作系统的一些基本概念但结合linux这个特定的OS,从总体上把握linux内核的设计思想,而深入理解Linux内核则比较具体的讲解内核的设计实现引用的代码比较多,比较细,比较杂,要细细分析。都挺不错,如何你比较入门,可以先看linux内核设计,但要结合代码分析,不然也很难入门,深入理解比较难,如果有一定水平,可以入手。
⑺ 有没有Linux内核源码指导书籍
1.《Linux内核设计与实现》
本书重在原理。适合入门的最佳图书。作者是为2.6内核加入了抢占的人,对调度部分非常精通,而调度是整个系统的核心,因此本书是很权威的。
2.《深入理解Linux内核》
此书比上一本多了些细节。是Linux内核黑客在推荐图书时的首选。写的比较简单易懂,适合刚刚接触LINUX内核的。
此书图表很多,形象地给出了关键数据结构的定义,与《Linux内核源代码情景分析》相比,本书内容紧凑,不会一个问题讲解动辄上百页,有提纲挈领的功用,但是深度上要逊于《Linux内核源代码情景分析》。
3.《LINUX设备驱动程序(第3版)》
这书强调动手实践!但它是讲解“设备驱动”的,不是最核心的东西,而且有些东西没硬件的话无法实践,可能更适合驱动开发的程序员吧
其中关于同步与互斥、内存分配的部分,感觉很不错。
4.《Linux内核源代码情景分析》
好,很经典,是浙大教授毛德操写的,可惜成书于2001年之后一直没有更新。分上下册。
很多是基于2.4内核讲解的需要注意。如果学习的话也建议学习2.6,2.6跟2.4比发生了很多显着改善,应该学习的。
全书内容博大精深,不是非常好懂,对细节问题描述比较清晰。但是感觉对内核的整体感觉不够强。另外缺少网络部分的分析。觉得不是很适合初学者。
5.《Linux内核源代码分析》
点评:面对中高级,这本书很好,对了解操作系统是一本不可多得的好书。
6. 《LINUXKERNEL技术手册》
参考手册,很薄,值得一看。
7.《深入Linux内核架构》
这本书针对的是比较新的内核版本2.6.24;内容比较全面,深入浅出。
如果没有对Linux内核的初步结构的认识,那么会看得比较吃力。建议可以一边去翻在国内已经闻名已经久的四本Linux内核着作(《Linux内核原代码情景分析》、《Linux内核设计与实现》、《深入理解Linux内核》、《Linux设备驱动程序》),再一边看这本书,把这本书当作一个补充或者当作一个内核框架图谱说明书来阅读,收效会更好。
8.《Linux内核完全注释》
主要描述和注释了Linux0.11内核全部源代码。对于初学Linux内核操作系统的人来讲,该书能够引领读者快速入门,并且能全面了解一个简单操作系统的工作机理。对于进一步学习现在的Linux内核具有非常大的指导作用。对于学习嵌入式应用的技术人员来讲,通过《完全注释》一书的学习也能迅速融入嵌入式应用领域。
9.《Orange S:一个操作系统的实现》
从只有二十行的引导扇区代码出发,一步一步地向读者呈现一个操作系统框架的完成过程。
⑻ 为什么Linux CFS调度器没有带来惊艳的碾压效果| CSDN博文精选
任何领域,革命性的碾压式推陈出新并不是没有,但是概率极低,人们普遍的狂妄在于,总是认为自己所置身的环境正在发生着某种碾压式的变革,但其实,最终大概率不过是一场平庸。
作者 | dog250
责编 | 刘静
出品 | CSDN博客
但凡懂Linux内核的,都知道Linux内核的CFS进程调度算法,无论是从2.6.23将其初引入时的论文,还是各类源码分析,文章,以及Linux内核专门的图书,都给人这样一种感觉,即 CFS调度器是革命性的,它将彻底改变进程调度算法。 预期中,人们期待它会带来令人惊艳的效果。
然而这是错觉。
人们希望CFS速胜,但是分析来分析去, 却只是在某些方面比O(1)调度器稍微好一点点 。甚至在某些方面比不上古老的4.4BSD调度器。可是人们却依然对其趋之若鹜,特别是源码分析,汗牛塞屋!
为什么CFS对别的调度算法没有带来碾压的效果呢?
首先,在真实世界,碾压是不存在的,人与人,事与事既然被放在了同一个重量级梯队比较,其之间的差别没有想象的那么大,根本就不在谁碾压谁。不能被小说电视剧电影蒙蔽了,此外,徐晓冬大摆拳暴打雷雷也不算数,因为他们本就不是一个梯队。
任何领域,革命性的碾压式推陈出新并不是没有,但是概率极低,人们普遍的狂妄在于,总是认为自己所置身的环境正在发生着某种碾压式的变革,但其实,最终大概率不过是一场平庸。
最终就出现了角力,僵持。
其次,我们应该看到,CFS调度器声称它会给交互式进程带来福音,在这方面CFS确实比O(1)做得好,但是惊艳的效果来自于粉丝的认同。Linux系统交互进程本来就不多,Linux更多地被装在服务器,而在服务器看来,吞吐是要比交互响应更加重要的。
那么以交互为主的Android系统呢?我们知道,Android也是采用了CFS调度器,也有一些事BFS,为什么同样没有带来惊艳的效果呢?
我承认,2008年前后出现CFS时还没有Android,等到Android出现时,其采用的Linux内核已经默认了CFS调度器,我们看下Android版本,Linux内核版本以及发行时间的关系:
Linux内核在2.6.23就采用了CFS调度器。所以一个原因就是没有比较。Android系统上,CFS没有机会和O(1)做比较。
另外,即便回移一个O(1)调度器到Android系统去和CFS做AB,在我看来,CFS同样不会惊艳,原因很简单,Android系统几乎都是交互进程,却前台进程永远只有一个,你几乎感受不到进程的切换卡顿,换句话说,即便CFS对待交互式进程比O(1)好太多,你也感受不到,因为对于手机,平板而言,你切换 APP 的时间远远大于进程切换的时间粒度。
那么,CFS到底好在哪里?
简单点说,CFS的意义在于, 在一个混杂着大量计算型进程和IO交互进程的系统中,CFS调度器对待IO交互进程要比O(1)调度器更加友善和公平 。理解这一点至关重要。
其实,CFS调度器的理念非常古老,就说在业界,CFS的思想早就被应用在了磁盘IO调度,数据包调度等领域,甚至最最古老的SRV3以及4.3BSD UNIX系统的进程调度中早就有了CFS的身影,可以说,Linux只是 使用CFS调度器 ,而不是 设计了CFS调度器 !
就以4.3BSD调度器为例,我们看一下其调度原理。
4.3BSD采用了1秒抢占制,每间隔1秒,会对整个系统进程进行优先级排序,然后找到优先级最高的投入运行,非常简单的一个思想,现在看看它是如何计算优先级的。
首先,每一个进程j均拥有一个CPU滴答的度量值Cj,每一个时钟滴答,当前在运行的进程的CPU度量值C会递增:
当一个1秒的时间区间ii过去之后,Cj被重置,该进程jj的优先级采用下面的公式计算:
可以计算,在一个足够长的时间段内,两个进程运行的总时间比例,将和它们的Base_PrioBase_Prio优先级的比例相等。
4.3BSD的优先级公平调度是CPU滴答驱动的。
现在看Linux的CFS,CFS采用随时抢占制。每一个进程j均携带一个 虚拟时钟VCj ,每一个时钟滴答,当前进程k的VCk会重新计算,同时调度器选择VC最小的进程运行,计算方法非常简单:
可见, Linux的CFS简直就是4.3BSD进程调度的自驱无级变速版本!
如果你想了解CFS的精髓,上面的就是了。换成语言描述,CFS的精髓就是 “ n个进程的系统,任意长的时间周期TT,每一个进程运行T/n的时间! ”
当然,在现实和实现中,会有80%的代码处理20%的剩余问题,比如如何奖励睡眠太久的进程等等,但是这些都不是精髓。
综上,我们总结了:
所以无论从概念还是从效果,Linux CFS调度器均没有带来令人眼前一亮的哇塞效果。但是还缺点什么。嗯,技术上的解释。
分析和解释任何一个机制之前,必然要先问,这个机制的目标是什么,它要解决什么问题,这样才有意义。而不能仅仅是明白了它是怎么工作的。
那么Linux CFS调度器被采用,它的目标是解决什么问题的呢?它肯定是针对O(1)算法的一个问题而被引入并取代O(1),该问题也许并非什么臭名昭着,但是确实是一枚钉子,必须拔除。
O(1)调度器的本质问题在于 进程的优先级和进程可运行的时间片进行了强映射!
也就是说,给定一个进程优先级,就会计算出一个时间片与之对应,我们忽略奖惩相关的动态优先级,看一下原始O(1)算法中一个进程时间片的计算:
直观点显示:
针对上述问题,2.6内核的O(1)O(1)引入了双斜率来解决:
直观图示如下:
貌似问题解决了,但是如果单单揪住上图的某一个优先级子区间来看,还是会有问题,这就是相对优先级的问题。我们看到,高优先级的时间片是缓慢增减的,而低优先级的时间片却是陡然增减,同样都是相差同样优先级的进程,其优先级分布影响了它们的时间片分配。
本来是治瘸子,结果腿好了,但是胳臂坏了。
本质上来讲,这都源自于下面两个原因:
固定的优先级映射到固定的时间片。
相对优先级和绝对优先级混杂。
那么这个问题如何解决?
优先级和时间片本来就是两个概念,二者中间还得有个变量沟通才可以。优先级高只是说明该进程能运行的久一些,但是到底久多少,并不是仅仅优先级就能决定的,还要综合考虑,换句话距离来说,如果只有一个进程,那么即便它优先级再低,它也可以永久运行,如果系统中有很多的进程,即便再高优先级的进程也要让出一些时间给其它进程。
所以,考虑到系统中总体的进程情况,将优先级转换为权重,将时间片转换为份额,CFS就是了。最终的坐标系应该是 权重占比/时间片 坐标系而不是 权重(或者优先级)/时间片 。应该是这个平滑的样子:
看来,Linux CFS只是为了解决O(1)O(1)中一个 “静态优先级/时间片映射” 问题的,那么可想而知,它又能带来什么惊艳效果呢?这里还有个“但是”,这个O(1)O(1)调度器的问题其实在计算密集型的守护进程看来,并不是问题,反而是好事,毕竟高优先级进程可以 无条件持续运行很久而不切换 。这对于吞吐率的提高,cache利用都是有好处的。无非也就侵扰了交互进程呗,又有何妨。
当然,使用调优CFS的时候,难免也要遇到IO睡眠奖惩等剩余的事情去设计一些trick算法,这破费精力。
对了,还要设置你的内核为HZ1000哦,这样更能体现CFS的平滑性,就像它宣称的那样。我难以想象,出了Ubuntu,Suse等花哨的桌面发行版之外,还有哪个Linux需要打开HZ1000,服务器用HZ250不挺好吗?
关于调度的话题基本就说完了,但是在进入下一步固有的喷子环节之前,还有两点要强调:
在CPU核数越来越多的时代,人们更应该关心 把进程调度到哪里CPU核上 而不是 某个CPU核要运行哪个进程 。
单核时代一路走过来的Linux,发展迅猛,这无可厚非,但是成就一个操作系统内核的并不单单是技术,还有别的。这些当然程序员们很不爱听,程序员最烦非技术方面的东西了,程序员跟谁都比写代码,程序员特别喜欢喷领导不会写代码云云。
Linux在纯技术方面并不优秀,Linux总体上优秀的原因是因为有一群非代码不明志的程序员在让它变得越来越优秀,另一方面还要归功于开源和社区。Linux的学习门槛极低,如果一个公司能不费吹灰之力招聘到一个Linux程序员的话,那它干嘛还要费劲九牛二虎之力去招聘什么高端的BSD程序员呢?最终的结果就是,Linux用的人极多,想换也换不掉了。
但无论如何也没法弥补Linux内核上的一些原则性错误。
Linux内核还是以原始的主线为base,以讲Linux内核的书为例,经典的Robert Love的《Linux内核设计与实现》,以及《深入理解Linux内核》,在讲进程调度的时候,关于多核负载均衡的笔墨都是少之又少甚至没有,如此经典的着作把很多同好引向了那万劫不复的代码深渊。于是乎,铺天盖地的CFS源码分析纷至沓来。
但其实,抛开这么一个再普通不过的Linux内核,现代操作系统进入了多核时代,其核心正是在cache利用上的革新,带来的转变就是进程调度和内存管理的革新。review一下Linux内核源码,这些改变早就已经表现了出来。
可悲的是,关于Linux内核的经典书籍却再也没有更新,所有的从传统学校出来的喜欢看书学习的,依然是抱着10年前的大部头在啃。
http :// www. ece.ubc.ca/~sasha/papers/eurosys16-final29.pdf
浙江温州皮鞋湿,下雨进水不会胖。
作者:CSDN博主“dog250”,本文首发于作者CSDN博客https://blog.csdn.net/dog250/article/details/957298 30 。
【END】