UNIX内核(5):内核开发的特点

简介: 原文转自:http://blog.chinaunix.net/uid-7471615-id-83765.html 内核开发不是洪水猛兽。一旦你了解到其中的规则,你就会发现,跟开发应用程序一样;两者区别在于要遵守的规则集合不一样。
原文转自:http://blog.chinaunix.net/uid-7471615-id-83765.html

内核开发不是洪水猛兽。一旦你了解到其中的规则,你就会发现,跟开发应用程序一样;两者区别在于要遵守的规则集合不一样。
Linux是UNIX家族的一员,而且其内核源代码唾手可得,因此这里用其来作说明。
规则上,与应用程序(运行于用户空间)的开发不同,主要表现在:
  1. 没有C库
  2. 用GNU C编程(对于Linux内核而言)
  3. 没有内存保护
  4. 在内核中很难使用浮点数
  5. 内核栈大小固定且很小
  6. 由于异步中断、抢占以及支持SMP,需要额外小心同步和并发
  7. 移植性问题
下面就来逐个解释。
内核没有链接任何C库。这里面涉及到很多问题,比如鸡生蛋还是蛋生鸡的问题:因为C库都会包裹一些系统调用,可是没有内核时就没有系统调用,那么……呵呵,明白了吧?另一个问题就是大小问题。任何一个C库,甚至其一个子集,对于内核来说都太大了。不过,不要着急,很多常用的库函数在内核中都有实现。
这里面涉及到一个著名的函数:printf(),内核提供了一个替代品:printk()。如果你要做内核开发,就会频繁使用该函数。记住:Linus本人不允许在内核中嵌入调试器(这是另外的话题,有兴趣的可以自己去google一下),因此很多情况下要依靠printk()。
毫无疑问,Linux的内核是用C语言写的。但所用的C并不是ANSI C,而是经过GNU扩展之后的C,这就是为什么Linux内核对于gcc编译器的依赖程度如此之高。GNU对C的扩展中就包括:内联函数(inline functions),分支预测和内联汇编(inline assembly)。分支预测用于判断哪些情况是几乎永远不可能发生的,或者哪些情况几乎永远都会发生——unlikely()和likely()。
当用户空间的代码访问非法地址时,内核能够捕获该错误,然后向进程发送SIGSEGV并终止进程。在UNIX世界,人们总是说kill/杀掉进程,其实,kill仅仅是用来向进程发送信号的,并不是杀掉它——太残忍了。这是题外话了,呵呵。那么,当内核代码访问非法地址时,谁来照顾内核呢?只能自己照顾自己了。非法的地址访问将导致oops,这是重大的问题,没人会告诉你访问了非法地址,但是你可以通过日志来查询/调试。
另外,内核内存是不分页,因此你没申请一个字节,物理内存就少掉一个字节。小心了!
在内核中使用浮点数非常困难,如果你想给自己找麻烦的话,可以试试。用户空间代码要使用浮点数指令时,一般来说会产生一个中断,内核捕获该中断并作相应的处理。然而,内核没法捕获自己。而且,要使用浮点指令,不但要保存浮点寄存器,还要做很多繁琐的事情——光看看内核如何为用户空间代码使用浮点数就知道了,可以参考进程调度里的上下文切换。
用户空间的程序可以在栈上申请大量的空间——定义足够多的局部变量,因为用户空间的栈非常大,而且可以动态增长。不过有些不够智能的系统做不到动态增长。然而,内核的栈非常小,而且无法动态增长。
作为一个抢占式多任务、支持对称多处理(SMP)的系统,同步和并发是任何一个内核hacker都需要时时刻刻小心的问题。调度器“兴之所至”,调度进程,这就需要同步;加上来自CPU外的各种中断导致内核需要对某些代码或数据加以保护。而抢占的意思就是,无论谁占用了CPU,都有可能被其他进程抢掉,内核也不例外。Linux对于竞态条件提供了spinlock(自旋锁)和semaphore(信号量)。
最后就是移植性问题。这个问题从来都不见简单,而且linux的目标是多种平台都能运行,因此移植性显得更为重要。字节序问题就是一个典型的移植性问题。然而,应用程序可能仅仅为一个平台开发。
看了这些,是不是觉得,其实内核开发也不难呢?
有雄心的hacker们,不要被OS kernel这个名词吓倒。看看Linux Kernel Development,准备好Linux内核源码,沏上一杯茶,然后你就可以开发内核了!
参考:
Linux Kernel Development, 2nd edition, by Robert Love
Copyleft (C) 2007 raof01. 本文可以用于除商业用途外的所有用途。若要用于商业用途,请与作者联系。
相关文章
|
存储 缓存 Unix
《现代体系结构上的UNIX系统:内核程序员的对称多处理和缓存技术(修订版)》——导读
虽然高速缓存能够在多处理器中增加有效的存储器带宽,但是高速缓存结构对于管理它所需要的操作系统开销有很大的影响,这又反过来影响了系统的整体性能。
2006 0
|
缓存 Unix 程序员
《现代体系结构上的UNIX系统:内核程序员的对称多处理和缓存技术(修订版)》——2.14 进一步的读物
本节书摘来自异步社区《现代体系结构上的UNIX系统:内核程序员的对称多处理和缓存技术(修订版)》一书中的第2章,第2.14节,作者:【美】Curt Schimmel著,更多章节内容可以访问云栖社区“异步社区”公众号查看
1543 0
|
缓存 算法 Unix
《现代体系结构上的UNIX系统:内核程序员的对称多处理和缓存技术(修订版)》——2.13 习题
一个程序通过每次将一个字保存到存储器连续的地址中来使存储器清零。观察一个系统,它采用带有写分配的写回高速缓存,在一开始被清零的存储器块并没有被高速缓存起来的时候,该系统会发生什么样的情况?假定行的大小比一个字大,第一次把数据保存到每一行中的时候会造成一次缺失,要从主存储器读取该行的内容。
1546 0
|
Java Unix
java的nio之:unix内核的五种I/O通信模型
一:根据unix的网络编程对I/O模型的分类,UNIX提供了5种I/O模型===>阻塞I/O模型:最常用的I/O模型。所有文件操作都是阻塞的。我们以套接字接口为例讲解此模型:在进程空间中调用recvfrom,其系统调用直到数据包到达且被复制到应用程序的缓冲区中或者发生错误时才返回。
1401 0