linux 内核开发的要点
内核编程时不能访问c库
内核编程时必须使用GNU C
内核编程时缺少像用户空间那样的内存保护机制
内核编程时浮点数很难使用
内核只有一个很小的定长堆栈
由于内核支持异步中断,抢占和SMP,因此必须时刻注意同步和并发
要考虑可移植性的重要性
------------------------------------------------------------------------------------------------
GNU C
1、内联函数(inline);
GNU的C编译器支持内联函数,反应出他的工作方式,函数会在调用他的位置进行展开。这么做可以消除函数调用和返回所带来的开销(寄存器存储和恢复),而且编译器会把调用函数的代码和函数本身放在一起进行优化,所以也有进一步优化代码的可能。不过这么做也有代价,代码会变长,这就意味着占用更多的内存空间和占用更多的指令缓存。内核开发者通常把那些对时间要求比较高,而本身代码比较短的函数定义成内联函数。
定义一个内联函数需要使用static关键字,并且用inline限定他。
内联函数必须在使用之前就定义好,否则编译器就没法把这个函数展开。实践中一般在同文件中定义内联函数。由于使用了static作为关键字进行限制,所以编译时不会为内联函数单独建立一个函数体。如果某个内联函数仅仅在某个源文件中使用,那么也可以把他定义在文件开始的地方
在内核中,为了类型安全的原因,首先使用内联函数而不是复杂的宏。
2内联汇编
gcc编译器支持在c函数中嵌入汇编指令。当然在内核编程的时候,只有知道对应的体系结构,才能使用这个功能。
linux的内核混合使用了c和汇编语言,在偏进体系结构的底层或者执行时间要求严格的地方,一般使用的是汇编语言。而内核的大多部分使用c写的。
3分支声明
对于条件选择语句,gcc内建了一条指令用于优化,在一个条件经常出现,或者条件很少出现的时候,编译器可以根据这条指令对条件分支选择进行优化。内核把这条指令封装成了宏。unlikely和likely在内核中得到广泛使用。
没有内存保护机制
内核中发生的内存错误会导致oops,这是内核中最常见的一类错误,在内核中不应该去做访问非法内存地址,应用空指针之类的事情。内核中的内存不分页
不要轻易的在内核中使用浮点数
体积小而固定的栈
同步和并发
内核很容易产生竞争条件。和单线程的用户控件程序不同,内核的许多特性都要求能够并发的访问共享数据,这就需要有同步机制保证不出现竞争条件,
尤其是:
@linux是抢占多任务操作系统 ,内核的进程调度程序即兴对程序进行调度和重新调度。内核必须对这些任务同步。
@linux内核支持多处理器系统。如果没有适当的保护,在两个或两个以上的处理器上运行的代码可能会同时访问共享的同一个资源。
@中断是异步到来的,完全不顾及当前正在执行的代码。也就是说,如果不加以适当的保护,中断完全有可能在代码访问共享资源的当中到来,这样,中断处理程序就有可能访问同一资源。
@linux内核可以抢占。所以不加以适当的保护,内核中一段正在执行的代码可能会被另一段代码抢占,从而可能导致几段代码同时访问相同的资源。