基础[Linux] 内核开发注意点

180 阅读1分钟

内核开发不同于以往我们编写应用程序那样肆无忌惮,内核的运行环境不具备很多“智能处理”,我们常常需要遵守某些规则和特点进行内核程序的编写。

  1. 内核编程不能访问C库和标准C头文件,因为很多C库是基于内核的,而且各种库水平参差不齐
  2. 内核编程必须使用GNU C,GNUC包括了标准C和扩展C,同时支持通用编译
  3. 内核编程缺乏用户空间那样的内存保护机制,内核无法发现非法内存访问
  4. 内核编程难以执行浮点数
  5. 内核给每个进程分配一个很小的定长栈,不宜做深递归
  6. 内核支持异步中断,抢占和SMP,因此必须更加关注同步和并发,Linux属于抢占式多任务系统
  7. 主要自己编写代码的可移植性

如我们在编写一些应用的时候常常使用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;
}