最近在看《LINUX设备驱动程序》,里面提到需要准备一个内核源代码树。在本人电脑上/usr/src里面查看到好几个版本的linux版本,这些其实就是编译好的内核源代码,也就是内核源代码树。
一、下载内核
我为了让自己熟悉一遍内核代码安装编译的过程,重新下载了 linux -5.4.0 .tar.xz ; https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.4.tar.xz这个版本来安装编译。
二、配置linux 内核
配置内核的方法很多,主要有如下几种:
1. #make menuconfig //基于ncurse库编制的图形工具界面
2. #make config //基于文本命令行工具,不推荐使用
3. #make xconfig //基于X11图形工具界面
4. #make gconfig //基于gtk+的图形工具界面
这里选择简单的输入,在终端输入以下命令:
make menuconfig
说一下配置:
对每一个配置选项,用户有三种选择,它们分别代表的含义如下:
<*>或[*]——将该功能编译进内核
[]——不将该功能编译进内核
[M]——将该功能编译成可以在需要时动态插入到内核中的代码
这一步是配置过程。配置你需要的内容。配置完成以后,保存退出。
三、编译安装
cd /usr/src/linux-5.4;
make -j4; //编译内核
make modules_install //安装模块
make headers_install //安装内核头文件
make –j4 install //安装内核
四、问题
1、编译时 出现错误,Makefile中TAB键和空格键的混用。图中灰白处应该为TAB按键结果,而不是空格,这个主要是因为直接拷贝的问题,自己手动写代码,记得用TAB键就行。
![72bfe68e155755fcdf8878917d9062d1.png](https://i-blog.csdnimg.cn/blog_migrate/6b4ba501c3421b8e0f0072430278c44f.png)
2、执行insmod时 提示 insmod: ERROR: could not insert module hello.ko: File exists。出现这个提示,执行一次rmmod hello 就可以了。
五、hello world模块
开始按照书上的测试hello world模块。控制台不能打印信息。查找资料得知:使用printk时,Linux内核根据日志级别,把消息打印到当前控制台上,这个控制台是一个字符设备。这些消息从终端输出的前提是日志输出级别小于console_loglevel。
网上提供的解决方法(原文链接:https://blog.csdn.net/wx601056818/article/details/80113983 )
1)命令
cat /proc/sys/kernel/printk
4 4 1 7
其中第一个“4”表示内核打印函数printk的打印级别,只有级别比他高的信息才能在控制台上打印出来(越小级别越高),既 0-3级别的信息:
#define KERN_EMERG "<0>" /* system is unusable */
#define KERN_ALERT "<1>" /* action must be taken immediately */
#define KERN_CRIT "<2>" /* critical conditions */
#define KERN_ERR "<3>" /* error conditions */
#define KERN_WARNING "<4>" /* warning conditions */
#define KERN_NOTICE "<5>" /* normal but significant condition */
#define KERN_INFO "<6>" /* informational */
#define KERN_DEBUG "<7>" /* debug-level messages */
我的程序中设置为“KERN_EMERG”为0级别,比4级别高。也就是说不是级别的问题。
2)输入以下命令
echo 8 > /proc/sys/kernel/printk //设置当前的日志级别为7 ,最低级别
按这条指令修改为8 4 1 7,结果还是无法打印。
3)不够打印级别的信息会被写到日志中可通过dmesg 命令来查看。
dmesg
于是我用dmesg来查看日志发现,以下提示:
![64a5d271b2f0a1c0a9454348de51a473.png](https://i-blog.csdnimg.cn/blog_migrate/7ecfabcc05f65bfd73032d98f4499806.png)
根据提示查找问题,发现linux内核自3.7内核版本以后有了内核签名机制。查找我的/usr/src/linux-5.4/.config关于签名部分的设置如下:
CONFIG_MODULE_SIG=y // y 表示开启了签名机制。
# CONFIG_MODULE_SIG_FORCE is not set // 模块必须有正确的签名才能正常使用,此处没设置
CONFIG_MODULE_SIG_ALL=y // y表示 内核在编译的时候,会主动去给模块签名
也就是说由于开启了签名机制而我的模块没有签名导致的。
解决方法:
1)添加证书
/usr/src/linux-5.4/scripts/sign-file sha512 /usr/src/linux-5.4/certs/signing_key.pem /usr/src/linux-5.4/certs/signing_key.x509 hello.ko;
按照网上资料按以上指令添加证书,结果还是无法打印输出。
2)修改.config的配置。由于usr文件夹受到写保护,还是在make menuconfig界面中修改方便。具体在Enable loadable module support (可加载模块支持)修改。
![ac02e94922a60b0bfb6cceffbb75ef01.png](https://i-blog.csdnimg.cn/blog_migrate/053ee57ce0c54ff33806577ec68b62a3.jpeg)
这三项CONFIG_MODULE_SIG,CONFIG_MODULE_SIG_FORCE,
CONFIG_MODULE_SIG_ALL=y 与界面配置参数的对应关系见valian1982:(转)linux内核配置中关于签名的配置选项。
我将CONFIG_MODULE_SIG对应的Module signature verification设置为n。
重新编译,安装 内核。
重新编译模块hello world,执行以下命令:
insmod ./hello.ko
结果还是无法打印,但是执行dmesg的hello的提示没有了。
![90e9062c992d5890fb2db04f3dc02ca6.png](https://i-blog.csdnimg.cn/blog_migrate/3985f904a9c481b1e28c382d8841ca86.png)
总结:到目前为止,我的hello模块无法将内容打印输出到控制台,等后面找到具体问题再来补上。