itpub路在何方
发表于 2016-07-20 22:37
我是一个平台运维人员,平时和linux操作系统打交道也很多,也有很多的感悟,对于linux内核态和用户态度我想首先我们要知道了解这两个态和为什么要有这个两个态
以及两个态的切换
内核态: CPU可以访问内存所有数据, 包括外围设备, 例如硬盘, 网卡. CPU也可以将自己从一个程序切换到另一个程序
用户态: 只能受限的访问内存, 且不允许访问外围设备. 占用CPU的能力被剥夺, CPU资源可以被其他程序获取
1,为什么要有用户态和内核态
由于需要限制不同的程序之间的访问能力, 防止他们获取别的程序的内存数据, 或者获取外围设备的数据, 并发送到网络, CPU划分出两个权限等级 -- 用户态 和 内核态
2,用户态与内核态的切换
所有用户程序都是运行在用户态的, 但是有时候程序确实需要做一些内核态的事情, 例如从硬盘读取数据, 或者从键盘获取输入等. 而唯一可以做这些事情的就是操作系统, 所以此时程序就需要先操作系统请求以程序的名义来执行这些操作.
这时需要一个这样的机制: 用户态程序切换到内核态, 但是不能控制在内核态中执行的指令
这种机制叫系统调用, 在CPU中的实现称之为陷阱指令(Trap Instruction)
他们的工作流程如下:
1.用户态程序将一些数据值放在寄存器中, 或者使用参数创建一个堆栈(stack frame), 以此表明需要操作系统提供的服务.
2.用户态程序执行陷阱指令
3.CPU切换到内核态, 并跳到位于内存指定位置的指令, 这些指令是操作系统的一部分, 他们具有内存保护, 不可被用户态程序访问
4.这些指令称之为陷阱(trap)或者系统调用处理器(system call handler). 他们会读取程序放入内存的数据参数, 并执行程序请求的服务
5.系统调用完成后, 操作系统会重置CPU为用户态并返回系统调用的结果
我想我们大学都学习过计算机组成原理中的批处理,CPU运行机制等原理,其实内核的学习还是很复杂的,很困难的,在我的工作中我是大概分为几个部分学习的。
1,常常看看API,即便读不能一次读懂也要坚持
“比起知道你所用技术的重要性,成为某一个特别领域的专家是不重要的。知道某一个具体API调用一点好处都没有,当你需要他的时候只要查询下就好了。”这句话源于我看到的一篇翻译过来的博客。我想强调的就是,这句话针应用型编程再合适不过,但是内核API就不完全如此。
内核相当复杂,学习起来很不容易,但是当你学习到一定程度,你会发现,如果自己打算写内核代码,到最后要关注的仍然是API接口,只不过这些API绝大部分是跨平台的,满足可移植性。内核黑客基本上已经标准化、文档化了这些接口,你所要做的只是调用而已。当然,在使用的时候,最好对可移植性这一话题在内核中的编码约定烂熟于心,这样才会写出可移植性的代码。就像应用程序一样,可以使用开发商提供的动态库API,或者使用开源API。同样是调用API,不同点在于使用内核API要比使用应用API了解的东西要多出许多。
当你了解了操作系统的实现---这些实现可都是对应用程序的基础性支撑啊---你再去写应用程序的时候,应用程序中用到的多线程,定时器,同步锁机制等等等等,使用共享库API的时候,联系到操作系统,从而把对该API的文档描述同自己所了解到的这些方面在内核中的相应支撑性实现结合起来进行考虑,这会指导你选择使用哪一个API接口,选出效率最高的实现方式。对系统编程颇有了解的话,对应用编程不无益处,甚至可以说是大有好处。
2,设计实现的本质,知道还是理解
操作系统是介于底层硬件和应用软件之间的接口,其各个子系统的实现很大程度上依赖于硬件特性。书上介绍这些子系统的设计和实现的时候,我们读过了,也就知道了,如果再深入考虑一下,为什么整体架构要按照这种方式组织,为什么局部函数要遵循这样的步骤处理,知其然,知其所以然,如果你知道了某个功能的实现是因为芯片就是这么设计的,CPU就是这么做的,那么你的疑问也就基本上到此为止了。再深究,就是芯片架构方面的设计与实现,对于程序员来讲,无论是系统还是应用程序员,足迹探究到这里,已经解决了很多疑问,因为我们的工作性质偏软,而这些东西实在是够硬。
比如,ULK3中讲解的中断和异常的实现,究其根源,那是因为Intel x86系列就是这么设计的,去看看Intel V3手册中相应章节介绍,都可以为ULK3中描述的代码实现方式找到注解。还有时间和定时器管理,同样可以在Intel V3 对APIC的介绍中获取足够的信息,操作系统就是依据这些硬件特性来实现软件方法定义的。
又是那句话,不是理解不理解的问题,而是知道不知道的问题。有时候,知道了,就理解了。在整个学习过程中,知道,理解,知道,理解,知道……,交叉反复。为什么开始和结尾都是知道,而理解只是中间步骤呢?世界上万事万物自有其规律,人类只是发现而已,实践是第一位的,实践就是知道的过程,实践产生经验,经验的总结就是理论,理论源于实践,理论才需要理解。我们学习内核,深入研究,搞来搞去,又回到了芯片上,芯片是物质的,芯片的功用基于自然界中物质本有的物理和电子特性。追本溯源,此之谓也。
3,动手写代码
纸上得来终觉浅,绝知此事要躬行。只看书是绝对不行的,一定要结合课本给出的编程建议自己敲代码。刚开始就以模块形式测试好了,或者自己编译一个开发版本的内核。一台机器的话,使用UML方式调试,内核控制路走到哪一步,单步调试看看程序执行过程,比书上的讲解更直观明了。一定要动手实际操作。
Godbach
发表于 2016-07-20 23:29
回复 91# itpub路在何方
LS 是第一帖啊 {:qq11:}欢迎多多分享。
henrystark
发表于 2016-07-21 14:59
回复 88# GFree_Wind
RPS是什么的缩写?并发长连接数?
Godbach
发表于 2016-07-21 15:02
回复 93# henrystark
Receive Packet Steering
Godbach
发表于 2016-07-21 15:04
回复 93# henrystark
实现了从系统层面将 packet 均衡的分不到多个 core 上,而不用依赖于网卡是否支持 RSS。
GFree_Wind
发表于 2016-07-21 21:28
回复 94# Godbach
其实。。。。这里的RPS是。。。。Request Per Second。。。。。
GFree_Wind
发表于 2016-07-21 21:30
回复 95# Godbach
Godbatch说的RPS解释也没错。。。
不过CentOS 6.5后面也加上了RPS补丁。我这里说的RPS是,指每秒钟处理的请求数目。CentOS7要比6.5高出50%以上。
这主要是内核对VFS的优化,之前的锁太多了。
GFree_Wind
发表于 2016-07-21 21:31
回复 96# GFree_Wind
英文缩写太多了,已经不够用了。。。
wait_rabbit
发表于 2016-07-22 00:11
回复 97# GFree_Wind
看到rps这个术语,倒是想起来,以前因为需要,写过一个简单的发包工具,其中一项就是rps,用户态的发包无论如何都压力不够。
后来改在 kernel 里直接收发,也就是调用 tcp_sendmsg 那一套接口,避免了数据从内核态到用户态的拷贝,最后终于达到目标。
Godbach
发表于 2016-07-22 08:53
回复 96# GFree_Wind
哦。这个我们一般称为 QPS {:qq23:}
页:
1
2
3
4
5
6
7
8
9
[10]
11
12