linux内核设计与实现 第二章,从内核出发

内核开发的特点

内核编程时既不能访问c库,也不能访问标准的c头文件。

内核编程必须使用,gnuc

内核编程时缺乏像用户空间那样的内存保护机制。

内核编程时难以执行浮点运算。

内核给每个进程只有一个很小的定长堆栈。

由于内核支持异步中断,抢占和smp,因此必须时刻注意同步和并发。

要考虑可移植的重要性。

定义一个内联函数的时候,需要使用static作为关键字,并且用inline限定它,比如:

static inline void wolf()。内联函数必须在使用之前就定义好,由于使用了Static关键字进行限制,所以编译时不会为内联函数单独建立一个函数体。如果一个内联函数仅仅在某一个源文件中使用。那么也可以把它定义在该文件开始的地方。

gcc编译器支持在c函数中嵌入汇编指令,我们通常使用asm()指令嵌入汇编代码。

对于条件选择语句,gcc内建了一条指令用于优化在一个条件经常出现,或者该条件很少出现的时候,编译器可以根据这条指定对条件分支选择语句进行优化。内核把这条指令封装成了宏,比如likely()和unlikely()。

如果一个用户进程试图进行一次非法的内存访问内核,就会发现这个错误,发送s i g s e g v信号,并结束整个进程。而如果内核自己非法访问内存,那后果就很难控制了。毕竟,谁能照顾内核呢?内核中发生的内存错误会导致oops,这是内核中经常出现的一种错误,在内核中不应该去访问非法的内存地址,引用空指针之类的事情,否则他可能会死掉,却根本不告诉你一声。在内核风险风长比外面大一些。

此外,内核中的内存都不分页。也就是说你每用掉一个字节,物理内存就减少一个字节。

在用户空间的进程进行浮点数操作的时候,内核会完成从整数操作到浮点数操作的模式转换。在执行浮点数指令时到底会做些什么呢?因体系结构不同,内核的选择也不相同,但是内核通常捕获陷阱并着手于整数到浮点方式的转变。

与用户空间进程不同,内核并不能完美的支持浮点操作,因为它本身不能陷入。在内核中使用浮点数时,除了要人工保存和恢复浮点寄存器,还有其他一些琐碎的事情要做。如果直接了当的回答,那就是别这么做了,除了一些基础的情况不要在内核中使用浮点数操作。

用户空间的程序可以从栈上分配大量的空间来存放变量,甚至巨大的结构体或者是包含数以千计的数据项的数组都没有问题。之所以可以这么做,是因为用户空间的栈本身比较大,而且还能随着发展而不断增大。

内核栈的准确大小随着体系结构而变,再x86上,栈的大小,在编译时配置,可以是4KB也可以是8KB,从历史上说内核栈的大小是两页,这意味着32位机的内核栈是8KB,而64位机是16KB,这是固定不变的,每个处理器都有自己的栈。

你可能感兴趣的:(linux内核设计与实现 第二章,从内核出发)