相信很多人在第一次接触到linux驱动程序的时候都遇到了两个基本的问题。
1.不知道怎么编译才能编译出linux模块程序。
2.写自己第一个linux驱动程序的时候,发现printk并不会向我们想想的那样把log信息显示在我们的终端上。
我自己也同样遇到了两个问题。
现在和大家分享下我从中学到的,当然肯定是不全面的。
1.linux模块的编译方法。
如果是一个简单的测试程序那么Makefile中只需要一个简单的语句就行了,就用LDD3中的hello world模块测试程序举例,Makefile文件中只需要一句obj-m := hello.o就行了。
然后编译模块:
make -C /kernel M=`pwd` modules
其中/kernel是你现在运行的内核的源文件地址。 “M=”之后是你的模块程序所在的地址。
2.printk()打印的log并没有显示在我们的终端上。
原因1:printk()有一个控制日志级别的字段,如果该字段的日记级别高于console默认的日志级别那么才会打印出来(数值越小日志级别越高,分为从0-7共计8个日志级别)。有一种简单的改变当前终端的日志级别的方法,echo 8 > /proc/sys/kernel/printk。理论上这样printk就能输出到终端了。但是我的没有。
原因2:syslogd守护进程的规则有问题,/etc/syslog.conf中定义了一些列规则,其中就包含数内核消息的处理规则,fedora中的syslogd守护进程叫做rsyslogd,相应它的规则配置文件叫rsyslog.conf,其中有一行”#kern.* /dev/console“它的意思是把所有日志级别的内核log都输出到/dev/console即我们的终端。我们只需要把该行的'#'去掉,重启,理论上那么内核log (printk()输出也是内核log)就会输出到终端了。但是我的还是不能。
原因3:系统中同时有klogd和syslogd守护进程那么不管日志级别是什么都不能输出到终端。
如果不能在终端上看到printk的输出,那么可以通过查看/var/log/messages文件,或运行dmesg命令查看,或查看/proc/kmsg文件获得信息,或是通过ctrl+alt+f2~f6进入系统文本模式装载模块,这样也可以看到prink()输出的信息,当然这里就准确对应原因1中所讲的规则。
最后说一下syslogd、直接通过/proc/kmsg、和dmesg读取printk输出缓冲区的区别:
syslogd:读取了缓冲区中的数据,不会删除缓冲区中的数据。
直接读取/proc/kmsg:读取了缓冲区中的数据后,将缓冲区中的数据删除(klogd默认就是采用这种方法)。
dmesg:在不刷新缓冲区的情况下获得缓冲区的内容,并将内容返回给stdout。
本文里的知识来至LDD3,和一位网友的博客(http://www.cnitblog.com/textbox/archive/2009/10/13/61785.html)。