内核开发不同于以往我们编写应用程序那样肆无忌惮,内核的运行环境不具备很多“智能处理”,我们常常需要遵守某些规则和特点进行内核程序的编写。
- 内核编程不能访问C库和标准C头文件,因为很多C库是基于内核的,而且各种库水平参差不齐
- 内核编程必须使用GNU C,GNUC包括了标准C和扩展C,同时支持通用编译
- 内核编程缺乏用户空间那样的内存保护机制,内核无法发现非法内存访问
- 内核编程难以执行浮点数
- 内核给每个进程分配一个很小的定长栈,不宜做深递归
- 内核支持异步中断,抢占和SMP,因此必须更加关注同步和并发,Linux属于抢占式多任务系统
- 主要自己编写代码的可移植性
如我们在编写一些应用的时候常常使用printf函数来做格式化输出,但是内核中并没有实现该函数,取而代之的是printk函数,该函数的功能与printf功能基本一致
printk是使用宏的方式定义了该函数,靠开发者自己实现
# linux/printk.h
#define printk(fmt, ...) printk_linux_wrap(_printk, fmt, ##__VA_ARGS__)
#define printk_linux_wrap(_p_func, _fmt, ...) \
({ \
__printk_index_emit(_fmt, NULL, NULL); \
_p_func(_fmt, ##__VA_ARGS__); \
})
# linux/printk.c
asmlinkage __visible int _printk(const char *fmt, ...)
{
va_list args;
int r;
va_start(args, fmt);
r = vprintk(fmt, args);
va_end(args);
return r;
}