Blog
Blog copied to clipboard
Chapter 2 Getting Started with the kernel
内核开发准备
No libc or Standard Headers
为了保证内核运行速度和体积,kernel不会链接标准C库或其他任何库。但是libc常用的一些函数库内核已经实现了,例如字符串处理相关的都在#include <linux/string.h>
。内核中不使用printf
,而是使用printk
函数。例如
printk(KERN_ERR" this is an error\n");
主要KERN_ERR
后面没有引号。
GNUC
因为使用GNU C,所有内核中常使用GNU C中的一些扩展。
Inline Functions
static inline void wolf(unsigned long tail_size)
内联函数一般用于函数会被多次调用的场景,节约系统资源,但频繁使用内联函数会使代码边长,从而运行时会占用更多内存,内核函数一般放在头文件中。
Inline Assembly
内联汇编用于偏近底层或对执行时间严格要求的地方。如下
unsigned int low, high;
asm volatile("rdtsc" : "=a" (low), "=d" (high));
Branch Annotation
Linux内核提供了两个宏来优化if分支判断
//预测error发生可能性几乎为0
if(unlikely(error)){
/*...*/
}
//预测success非常可能发生
if(likely(success)){
/*...*/
}
No Memory Protection
因为内核是最低层的程序,所以如果内核访问的非法内存,那么整个系统都会挂掉!!所以内核开发的风险比用户程序开发的风险要大。而且,内核中的内存是不分页的,每用一个字节的内存,物理内存就少一个字节。所以内核中使用内存一定要谨慎。
No Use of Floating Float
除非在非常罕见的场景,否则不要在内核中使用浮点数。
Small, Fixed-size Stack
内核栈的大小有编译内核时决定的,对于不用的体系结构,内核栈的大小虽然不一样,但都是固定的。查看内核栈大小的方法:
ulimit -a | grep "stack size"
Synchronization and Concurrency
Linux是多用户的操作系统,所以必须处理好同步和并发操作,防止因竞争而出现死锁。
Importance of Portability
Linux内核可用于不用的体现结构,支持多种硬件。所以开发时要时刻注意可移植性,尽量使用体系结构无关的代码。