Linux内核学习趣谈
本文原创是freas_1990,转载请标明出处:http://blog.csdn.net/freas_1990/article/details/9304991
从大二开始学习Linux内核,到现在已经4年了。在大学的时候,学习Linux内核仅仅是作为一种爱好,因为国内罕有人能在本科毕业之后直接从事Linux内核研发工作,而哦也从未打算读研。
学习内核是一件很有趣的事情。仅仅是出于兴趣。当很想知道命令是如何从键盘输入到计算机并且关联到进程的时候,我翻出了Linux内核的源代码。然而,面对的问题越来越多,好像一个潘多拉盒子,一旦打开了,就一发不可收拾。当很想知道什么是进程的时候,会去翻阅内核关于进程的结构体。然而,更复杂的问题是,内核的作者是怎么在一个裸机上相处要把“进程”这个概念意淫出来的呢?这一系列的问题对我的吸引好似毒瘾。
操作系统本质的任务是为了是计算机工作更有效率,各种资源压榨更彻底。所以,内核hacker本质上是最优秀的吸血鬼。
正因为操作系统需要压榨硬件的资源,所以需要对硬件比较熟悉——当然,并不是说每个内核工程师都是驱动工程师。有的可能只是对算法比较有研究,优化了某一个数据结构或者算法。然而,所有的优化都是为了使硬件干活儿更有效率,所以,对硬件的熟悉是最基础的——如果不熟悉硬件的特性,那么,即便做了很多的优化,也是为了优化而优化。
与操作系统关系最密切的硬件莫过于CPU。关于CPU,最核心的莫过于多任务管理、内存管理。前者是操作系统的两大核心之一,后者是前者的基础。
关于CPU的任务,有三个概念必须要搞清楚。任务的定义、上下文切换、内存的分段segment(注意与汇编里的代码段、数据段、堆栈段区分,这三个概念一般是在同一个物理内存的segment内的)。其中,任务基本上是意淫出来的(个人观点)。对于CPU而言,需要做的就是去查IP指向了内存的哪里,然后去执行,至于是否是一个任务,它本身不在意。而当intel人为地定义出一个任务概念之后,关于任务这个对象的属性就出来了,intel用一个专用tr寄存器用于存储指向当前任务的任务描述符地址。当tr指向哪一条任务描述符了,哪一个任务就被意淫为正在执行。当tr指向另外一个任务描述符的时候,另外一个任务就是正在执行了。Linux内核有专门的switch_to()这样一个宏定义(实际上是汇编指令)来做这个事儿。这个过程被称为上下文切换。当然,上下文切换有很多复杂的工作要做,最基本的就是要把当前的任务的执行情况保存起来。
如何保存呢?
当然要用到栈了。(栈并非是C语言专用的数据结构,而是一种通用的数学概念,一种通用的机制,只不过天朝的叫兽很喜欢把C和栈捏到一起意淫)。
早期的Linux内核为一个进程分配了一个page减去task_struct大小的内核栈,用于存储内核态的上下文信息。
说远了,回到上下文切换的概念。
大家都知道上下文切换是一个很耗费资源的工作。应该尽量避免。
有一个很傻很天真的问题摆在这里。
既然上下文切换是应该避免的问题,为什么内核还要提供上下文切换的功能呢?那不是在自己打嘴巴吗?
准确的说,这是一个关于人性本自私的话题的探讨——觉得穿越了吧?
说上下文切换不好,是站在应用(说话者所支持的应用)的立场来说话的。比如说,一个Linux企业系统出现了大量的上下文切换,DBA抱怨说,这个系统太fuck了,Oracle还怎么跑嘛?他是站在Oracle的角度来说话的。
而在操作系统的角度,它觉得自己已经协调好了各个任务的资源配置,尽最大的努力让各个任务都能均衡执行。至于各个任务性能还是不能让人满意,关键问题是应用太多了——老子就那么两个核,丢过来几万个任务,上下文切换能不多吗?我日。
至于在CPU的角度,内存里有多少代码,老子就跑多久,一个任务是跑,一万个任务也是跑。老子跑就是了,你应用设计的合不合理,应用跑得爽不爽,关老子鸟事。
好吧,再回到内存分段的概念。
现代操作系统用的其实是分页管理。至于分段管理,那是30年前过时的技术了——可笑的是,直到2013年,天朝很多高校的汇编课程讲解的重点就是80x86的分段管理(还是实模式那种)。
80x86系列的分页管理核心在于逻辑地址、虚拟地址、线性地址、物理地址之间的转换。页目录、页表实现的机制。
CPU的三个概念就占了很大的篇幅了。说了这么多,不是想在这里讲解很多知识。主要是想说明,Linux内核学习是一个很复杂的问题,是一个真正的兴趣驱动的过程。相对而言,如果你选择一个商业产品,无论你多么自信地说自己爱Oracle数据库,恨不能天天与它做爱,但是,参加一个月培训后,就能正常干活了——对你而言实在是太容易了。
你需要持续的动力,持续的热情。需要能在一个夜晚读内核源代码读到黑夜变白天。
有这种战斗的精神,无论是Linux内核,还是你喜欢的女孩子,还是事业,都是你的。
Linux内核学习趣谈的更多相关文章
- Linux 内核学习的经典书籍及途径
from:http://www.zhihu.com/question/19606660 知乎 Linux 内核学习的经典书籍及途径?修改 修改 写补充说明 举报 添加评论 分享 • 邀请回答 ...
- 关于Linux内核学习的误区以及相关书籍介绍
http://www.hzlitai.com.cn/article/ARM9-article/system/1605.html 写给Linux内核新手-关于Linux内核学习的误区 先说句正经的:其实 ...
- linux内核学习之二:编译内核
在linux内核学习系列的第一课中讲述了搭建学习环境的过程(http://www.cnblogs.com/xiongyuanxiong/p/3523306.html),环境搭好后,马上就进入到下一环节 ...
- linux内核学习之一:环境搭建--安装Debian7.3
本系列文章假设读者已对linux有一定的了解,其实学习linux内核不需要有很深的关于linux的知识,只需要了解以下内容:linux基础知识及基本shell命令:现代操作系统的基本概念:C语言和gc ...
- Linux内核学习笔记-2.进程管理
原创文章,转载请注明:Linux内核学习笔记-2.进程管理) By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...
- Linux内核学习笔记-1.简介和入门
原创文章,转载请注明:Linux内核学习笔记-1.简介和入门 By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...
- Linux 内核学习经验总结
Linux 内核学习经验总结 学习内核,每个人都有自己的学习方法,仁者见仁智者见智.以下是我在学习过程中总结出来的东西,对自身来说,我认为比较有效率,拿出来跟大家交流一下. 内核学习,一偏之见:疏漏难 ...
- Linux内核分析——Linux内核学习总结
马悦+原创作品转载请注明出处+<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 Linux内核学习总结 一 ...
- Linux内核学习笔记二——进程
Linux内核学习笔记二——进程 一 进程与线程 进程就是处于执行期的程序,包含了独立地址空间,多个执行线程等资源. 线程是进程中活动的对象,每个线程都拥有独立的程序计数器.进程栈和一组进程寄存器 ...
随机推荐
- 自己编译的openwrt在开机时一直打印jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found...的错误提示
具体的输入信息是这样的. uboot> http Link down: eth0 Ethernet mode (duplex/speed): / Mbps HTTP server is star ...
- Python 3语法小记(九) 异常 Exception
常见异常: Exception 所有异常的基类 AttributeError 特性应用或赋值失败时引发 IOError ...
- 干净的架构The Clean Architecture
干净的架构The Clean Architecture 这是著名软件大师Bob大叔提出的一种架构,也是当前各种语言开发架构.干净架构提出了一种单向依赖关系,从而从逻辑上形成一种向上的抽象系统. 我们经 ...
- python进程池剖析(三)
之前文章对python中进程池的原理.数据流以及应用从代码角度做了简单的剖析,现在让我们回头看看标准库中对进程池的实现都有哪些值得我们学习的地方.我们知道,进程池内部由多个线程互相协作,向客户端提供可 ...
- 大约ActionContext.getContext()使用体验
这是我在另一个人的博客看了,原来博客的时间长一点.我把它简化了一下,运营商,以方便它看起来. 为了避免与Servlet API耦合在一起,方便Action类做单元測试,Struts 2对HttpSer ...
- 谈一谈struts2和springmvc的拦截器
最近涉及到了两个项目,都需要考虑全局的拦截器,其功能就是判断session的登陆状态,如果session信息完好,可以从中取得相应的信息,则放行,否则拦截,进入重定向的uri. 既然是全局的拦截器,其 ...
- ajax 请求数据
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- vi/vim多行注释和取消注释
多行注释: 1. 进入命令行模式,按ctrl + v进入 visual block模式,然后按j, 或者k选中多行,把需要注释的行标记起来 2. 按大写字母I,再插入注释符,例如// 3. 按esc键 ...
- Oracle组函数、多表查询、集合运算、数据库对象(序列、视图、约束、索引、同义词)等
count组函数:(过滤掉空的字段) select count(address),count(*) from b_user max() avg() min(),sum() select sum(age ...
- 实现栈最小元素的min函数
#include<iostream> #include<stack> using namespace std; class min_stack { public: void p ...