|
原创文章版权所有!如需转载,请注明出处: tekkman.cublog.cn ,谢谢合作!!!!!
Linux设备驱动程序学习(2)-调试技术
今天进入《Linux设备驱动程序(第3版)》第四章调试技术的学习。
一、内核中的调试支持
在前面已经建议过:学习编写驱动程序要构建安装自己的内核(标准主线内核)。最重要的原因之一是:内核开发者已经建立了多项用于调试的功能。但是由于这些功能会造成额外的输出,并导致能下降,因此发行版厂商通常会禁止发行版内核中的调试功能。
为了实现内核调试,我在内核配置上增加了几项:
Kernel hacking --->
Magic SysRq key
Kernel debugging
Debug slab memory allocations
Spinlock and rw-lock debugging: basic checks
Spinlock debugging: sleep-inside-spinlock checking
Compile the kernel with debug info
Magic SysRq key
Device Drivers --->
Generic Driver Options --->
Driver Core verbose debug messages
General setup --->
Configure standard kernel features (for small systems) --->
Load all symbols for debugging/ksymoops
书上介绍的还有其他配置,有的我不需要,或是s3c2440不支持,菜单里看不见。
二、通过打印调试
(1)printk
首先,printk有8个loglevel,定义在<linux/kernel.h>中:
#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 */
未指定优先级的默认级别定义在/kernel/printk.c中:
#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
当优先级的值小于console_loglevel这个整数变量的值,信息才能显示出来。而console_loglevel的初始值DEFAULT_CONSOLE_LOGLEVEL也定义在/kernel/printk.c中: #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define __LIBRARY__ /* _syscall3 and friends are only available through this */
#include <linux/unistd.h>
/* define the system call, to override the library function */
_syscall3(int, syslog, int, type, char *, bufp, int, len);
int main(int argc, char **argv)
{
int level;
if (argc==2) {
level = atoi(argv[1]); /* the chosen console */
} else {
fprintf(stderr, "%s: need a single arg\n",argv[0]); exit(1);
}
if (syslog(8,NULL,level) < 0) {
fprintf(stderr,"%s: syslog(setlevel): %s\n",
argv[0],strerror(errno));
exit(1);
}
exit(0);
}
最关键的语句我不理解,没有找到相关资料。但是通过在ARM9板上的实验表明:程序是ok的!我用Hello world模块做了实验,现象和书上的一致。
[Tekkaman2440@SBC2440V4]#cd /tmp/
[Tekkaman2440@SBC2440V4]#./setlevel 1
[Tekkaman2440@SBC2440V4]#cd /lib/modules/
[Tekkaman2440@SBC2440V4]#insmod hello.ko
[Tekkaman2440@SBC2440V4]#rmmod hello
[Tekkaman2440@SBC2440V4]#cd /tmp/
[Tekkaman2440@SBC2440V4]#./setlevel 7
[Tekkaman2440@SBC2440V4]#cd /lib/modules/
[Tekkaman2440@SBC2440V4]#insmod hello.ko
Hello, Tekkaman Ninja !
[Tekkaman2440@SBC2440V4]#rmmod hello
Goodbye, Tekkaman Ninja !
Love Linux !Love ARM ! Love KeKe !
[Tekkaman2440@SBC2440V4]#
还有通过对/proc/sys/kernel/printk的访问来改变console_loglevel的值:
[Tekkaman2440@SBC2440V4]#echo 1 > /proc/sys/kernel/printk
[Tekkaman2440@SBC2440V4]#cat /proc/sys/kernel/printk
1 4 1 7
[Tekkaman2440@SBC2440V4]#insmod hello.ko
[Tekkaman2440@SBC2440V4]#rmmod hello
[Tekkaman2440@SBC2440V4]#echo 7 > /proc/sys/kernel/printk
[Tekkaman2440@SBC2440V4]#cat /proc/sys/kernel/printk
7 4 1 7
[Tekkaman2440@SBC2440V4]#insmod hello.ko
Hello, Tekkaman Ninja !
[Tekkaman2440@SBC2440V4]#rmmod hello
Goodbye, Tekkaman Ninja !
Love Linux !Love ARM ! Love KeKe !
四个数字的含义:当前的loglevel、默认loglevel、最小允许的loglevel、引导时的默认loglevel。
/* Macros to help debugging */
#undef PDEBUG /* undef it, just in case */
#ifdef SCULL_DEBUG
# ifdef __KERNEL__
/* This one if debugging is on, and kernel space */
# define PDEBUG(fmt, args...) printk( KERN_DEBUG "scull: " fmt, ## args)
# else/* This one for user space */
# define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
# endif
#else
# define PDEBUG(fmt, args...) /* not debugging: nothing */
#endif
#undef PDEBUGG
#define PDEBUGG(fmt, args...) /* nothing: it's a placeholder */
Makefile中要添加的语句:
# Comment/uncomment the following line to disable/enable debugging
DEBUG = y
# Add your debugging flag (or not) to CFLAGS
ifeq ($(DEBUG),y)
DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
else
DEBFLAGS = -O2
endif
CFLAGS += $(DEBFLAGS)
为了避免printk重复输出过快而阻塞系统,内核使用以下函数跳过部分输出:
典型的应用如下:
if (printk_ratelimit( ))
printk(KERN_NOTICE "The printer is still on fire\n");
可以通过修改/proc/sys/kernel/printk_ratelimit(重开信息前应等待的秒数)和/proc/sys/kernel/printk_ratelimit_burst(在速度限制前可接受的信息数)来定制printk_ratelimit的行为。
int print_dev_t(char *buffer, dev_t dev);
char *format_dev_t(char *buffer, dev_t dev);
两个函数的唯一区别是:
三、通过查询调试
多数情况中,获取相关信息的最好方法是在需要的时候才去查询系统信息,而不是持续不断地产生数据。
使用/proc文件系统
/proc文件系统是一种特殊的、由软件创建的文件系统,内核使用他向外界导出信息。/proc下面的每个文件都绑定于一个内核函数,用户读取其中的文件时,该函数动态的生成文件的内容。如以前用过的:
[Tekkaman2440@SBC2440V4]#cat /proc/devices
Character devices:
1 mem
2 pty
3 ttyp
4 /dev/vc/0
4 tty
4 ttyS
5 /dev/tty
5 /dev/console
5 /dev/ptmx
7 vcs
10 misc
13 input
14 sound
81 video4linux
89 i2c
90 mtd
116 alsa
128 ptm
136 pts
180 usb
189 usb_device
204 s3c2410_serial
252 scull
253 usb_endpoint
254 rtc
Block devices:
1 ramdisk
256 rfd
7 loop
31 mtdblock
93 nftl
96 inftl
179 mmc
使用/proc的模块必须包含<linux/proc_fs.h>,而使用seq_file接口要包含<linux/seq_file.h>。
具体的应用方法看源程序、做实验更有效果。
至于其他的调试方法,如gdb、LTT、SysRq等方法,在其他的书籍,如:《嵌入式Linux系统开发技术详解-基于ARM》、《构建嵌入式Linux系统》等,上讲解的更为详细,以后专门花时间研究。
四、源码实验
模块程序链接:模块程序
模块测试程序链接:模块测试程序
实验现象:
[Tekkaman2440@SBC2440V4]#cd /lib/modules/
[Tekkaman2440@SBC2440V4]#insmod scull_debug.ko scull_nr_devs=1 scull_quantum=6 scull_qset=2
[Tekkaman2440@SBC2440V4]#cd /tmp/
[Tekkaman2440@SBC2440V4]#./scull_test
write code=6
write code=6
write code=6
write code=2
read code=6
read code=6
read code=6
read code=2
[0]=0 [1]=1 [2]=2 [3]=3 [4]=4
[5]=5 [6]=6 [7]=7 [8]=8 [9]=9
[10]=10 [11]=11 [12]=12 [13]=13 [14]=14
[15]=15 [16]=16 [17]=17 [18]=18 [19]=19
[Tekkaman2440@SBC2440V4]#cd /proc/
[Tekkaman2440@SBC2440V4]#ls
1 751 cmdline kallsyms stat
2 769 cpu kmsg swaps
3 77 cpuinfo loadavg sys
4 778 crypto locks sysrq-trigger
5 779 devices meminfo sysvipc
59 78 diskstats misc timer_list
6 781 driver modules tty
60 783 execdomains mounts uptime
63 785 filesystems mtd version
65 79 fs net vmstat
707 80 ide partitions yaffs
708 819 interrupts scullmem zoneinfo
709 asound iomem scullseq
710 buddyinfo ioports self
742 bus irq slabinfo
[Tekkaman2440@SBC2440V4]#cat scullmem
Device 0: qset 2, q 6, sz 20
item at c071ebd4, qset at c071ef7c
item at c071ef14, qset at c071eee0
0: c071eeac
1: c071ee78
[Tekkaman2440@SBC2440V4]#cat scullseq
Device 0: qset 2, q 6, sz 20
item at c071ebd4, qset at c071ef7c
item at c071ef14, qset at c071eee0
0: c071eeac
1: c071ee78
[Tekkaman2440@SBC2440V4]#rmmod scull_debug
[Tekkaman2440@SBC2440V4]#ls
1 742 buddyinfo iomem self
2 751 bus ioports slabinfo
3 769 cmdline irq stat
4 77 cpu kallsyms swaps
5 778 cpuinfo kmsg sys
59 779 crypto loadavg sysrq-trigger
6 78 devices locks sysvipc
60 781 diskstats meminfo timer_list
63 783 driver misc tty
65 785 execdomains modules uptime
707 79 filesystems mounts version
708 80 fs mtd vmstat
709 824 ide net yaffs
710 asound interrupts partitions zoneinfo
发表于: 2007-10-25,修改于: 2007-10-26 16:10,已浏览4841次,有评论0条 推荐 投诉
网友评论
好文章,我是从你的第一章开始看的,今天9号看到你又有新内容,学不少东西,请坚持下去,加油啊
很不错啊,我几乎每天都来学习你的经验,感觉收益非浅,加油啊!
我觉得最好的方式就是有人交流^_^我很想与你交流,我的QQ32313055
我学arm一年多了,可是水平比阁下差远了。看完文章,收获良多,非常感谢!
向Tekkaman Ninja致敬,你的学习态度和学习方式都值得我们借鉴!
圣诞快乐!
让我学到了很多东西,
很好的文章啊,我正在学习驱动开发,刚刚入门,谢谢啊
write error! code=-1
write ok! code=21
read ok! code=20
[0]=0 [1]=0 [2]=1 [3]=2 [4]=3
[5]=4 [6]=5 [7]=6 [8]=7 [9]=8
[10]=9 [11]=10 [12]=11 [13]=12 [14]=13
[15]=14 [16]=15 [17]=16 [18]=17 [19]=18
我改了一下makefile在pc上运行是这个结果
所有的源码都在友善之臂SBC2440V4上反复测试过(内核为2.6.22.2)。所以基本上只要改Makefile就好(除了硬件相关的部分)。如果有问题可以将详细的情况发邮件给我,有空我会回复的。
写的真的很好
我们老师就让写一个字符设备驱动程序,我都是通过在你的网页上学会的所有的东西。
赞一个,总结的很好
曾经研究过ldd3,没有认真写下读书笔记,以后还得好好再看下了
请问怎么使用drivers/spi/atmel_spi.c提供的驱动呢?在/dev下没有相应的设备节点,怎么才能在用户空间访问设备?如果自己写一个驱动注册一个spi驱动可以使用其中哪些函数接口?诚请帮忙
今天看了你的文章很感慨,希望能共同学习。有个问题想问,
请问当insmod scull.ko scull_quantum=6 scull_qset=2
数据已经溢出了,为什么20个数据还能写进去。谢谢了
这个和scull的数据结构有关,你认真看看《Linux设备驱动程序学习(1)-字符设备驱动程序》,中的图,你可能对scull的数据结构还没有理解透,scull_quantum代表了一个quantum的字节数,scull_qset代表一个qset包含几个quantum,但是还有qset没有限制,也就是说我写20个字节进去,一个scull中有2个qset。
总结的太好了。
有一个问题想请教一下。看模块中定义了一个char *whom = "world"
这是一个字符串常量,如果按照标准C的话,指针指向的是一个常量字符串才对,其中的内容不能修改。比如whom[2]='a';这样会有段错误,为什么在内核中这样操作是合法的呢?
我觉得你这样是定义一个字符串变量,所以可以修改。我学硬件的,对c研究还不深,不知见解是否正确?
lz的经验和态度值得我们学习,向你致敬!
很不错,尤其是有源码和测试程序。
你好!刚接触linux驱动,看到你这里的设备模型分析,很不错
帮了我的大忙!
我有一个问题,对于nand flash,作为一个块设备,应用程序如何去访问它,对它进行擦除、读写等操作?
因为它不象字符设备那样有可供调用的系统调用
块设备我暂时还没看,见谅
我也想知道块设备的一些知识,老是来你这儿看,希望能得到一些帮助,呵呵
块设备我还没看啊,苦于没时间和没板做实验
问一个问题:
你上文提到的测试程序是不是相当于linux系统的应用程序,实现对驱动的系统调用?
如果是这样,那么测试程序应该放在什么路径下,用什么编译器进行编译,因为我看到你有写测试程序的makefile,是不是也要用交叉编译器对它进行编译阿,可是这样的话,生成的目标代码是arm格式的,不能在pc上直接执行。
麻烦你帮我解答一下这个疑问。
刚刚接触linux,问得问题比较愚蠢,见笑了
测试程序是应用程序,在板上运行
要交叉编译
总结得很好 就像上完课了要复习
很好的学习总结,受益匪浅!
[root@(none) scullc]# insmod scullc.ko
Using scullc.ko
nfs: server 222.31.45.9 not responding, still trying
nfs: server 222.31.45.9 not responding, still trying
nfs: server 222.31.45.9 not responding, still trying
我按照傅大哥写的模块,一装载的时候就出错了........
里面的网络没问题,就是装载了模块后出问题的........
傅大哥知道怎么回事吗???????
我是刚接触linux的。今天看到你的总接非常高兴,做的太详细了。。。
我想问一下,是否可以讲解一下container_of是怎么用的。。
谢谢!
关于楼主描述的:
最关键的“syslog(8,NULL,level)”语句我不理解,没有找到相关资料。但是通过在ARM9板上的实验表明:程序是ok的!我用Hello world模块做了实验,现象和书上的一致。
我查阅了一下,应该这么理解:
原型是:int syslog(int type, char *bufp, int len);
根据type来采取对内核ring buffer的操作,并设置consele_loglevel的值为len。
type参数有以下几种值:
/*
* Commands to sys_syslog:
*
* 0 -- Close the log. Currently a NOP.
* 1 -- Open the log. Currently a NOP.
* 2 -- Read from the log.
* 3 -- Read up to the last 4k of messages in the ring buffer.
* 4 -- Read and clear last 4k of messages in the ring buffer
* 5 -- Clear ring buffer.
* 6 -- Disable printk’s to console
* 7 -- Enable printk’s to console
* 8 -- Set level of messages printed to console
* 9 -- Return number of unread characters in the log buffer
*/
返回值的描述:
In case of error, -1 is returned, and errno is set. Otherwise,
for type equal to 2, 3 or 4, syslog() returns the number of
bytes read, and otherwise 0.
不妥之处请指教,谢谢。
文章写的很好,刚开始学驱动,有很多地方都不是很懂,很想跟你学习啊,想请教一下学习linux设备驱动的方法。
问一个很弱的问题,楼主的源码文件是如何存储在cublog里面的,敬请告知,不胜感激
write code=6
write code=6
write code=6
write code=2
read code=6
read code=6
read code=6
read code=2
[0]=0 [1]=1 [2]=2 [3]=3 [4]=4
[5]=5 [6]=6 [7]=7 [8]=8 [9]=9
[10]=10 [11]=11 [12]=12 [13]=13 [14]=14
[15]=15 [16]=16 [17]=17 [18]=18 [19]=19
看你的测试程序中 输出语句 要么是 work error! code=.. 或者 work ok! code=.. 上面的代码输出 work code=... 既没有error! 也没有ok! 什么原因啊?
在字符驱动那张图 scull_device所指的链表中 Scull_qset 这种结构的个数如何确定呢。
insmod scull_debug.ko scull_nr_devs=1 scull_quantum=6 scull_qset=2后
我测试的结果是:
write error! code=6
write error! code=6
write error! code=6
write ok! code=2
read error! code=6
read error! code=6
read error! code=6
read ok! code=2
[0]=0 [1]=1 [2]=2 [3]=3 [4]=4
[5]=5 [6]=6 [7]=7 [8]=8 [9]=9
[10]=10 [11]=11 [12]=12 [13]=13 [14]=14
[15]=15 [16]=16 [17]=17 [18]=18 [19]=19
请问如何解释啊。
从楼主这里学到不少东西
void kobject_del(struct kobject *kobj); /*是 kobject_del 和 kobject_put 的结合*/写错了
编译的时候出现
[root@localhost scull]# make modules
make -C /home/alu/mywork/systems/linux-2.6.22.6 M=/home/soso/ldd3/scull modules
make[1]: Entering directory `/home/alu/mywork/systems/linux-2.6.22.6'
CC [M] /home/soso/ldd3/scull/scull_t1.o
cc1: invalid option `little-endian'
cc1: invalid option `arm'
cc1: invalid option `apcs'
cc1: invalid option `no-sched-prolog'
cc1: invalid option `apcs-32'
cc1: invalid option `no-thumb-interwork'
cc1: invalid option `tune=arm9tdmi'
cc1: invalid option `alignment-traps'
cc1: unrecognized option `-Wdeclaration-after-statement'
make[2]: *** [/home/soso/ldd3/scull/scull_t1.o] 错误 1
make[1]: *** [_module_/home/soso/ldd3/scull] 错误 2
make[1]: Leaving directory `/home/alu/mywork/systems/linux-2.6.22.6'
make: *** [modules] 错误 2
请教大哥 这个大概可能是什么问题啊 那么多参数无效
内核版本2.6.22.6
arm-linux-gcc -v
gcc version 3.3.6
"include/linux/moduleparam.h文件中有关于module_param_array宏的说明,这里第三个参数的作用是:
*nump is set to number they actually specified
所以这里的TNparam_nr并不是限制输入数组参数的数目,而是实际数据的大小。
可以在上面的示例代码中加一句:
printk(KERN_ALERT "TNparam_nr=%d\n",TNparam_nr);
得到的结果会是你实际输入的数组元素个数。
BTW:笔记写得这么详细,我都懒得写了,直接收藏你的笔记了:-)
感谢兄台指点!!!!!!!
新学驱动开发 跟着ldd3看不懂 来支持下你
/* Then follow the list */
while (n--) {
if (!qs->next) {
qs->next = kmalloc(sizeof(struct scull_qset), GFP_KERNEL);
if (qs->next == NULL)
return NULL; /* Never mind */
memset(qs->next, 0, sizeof(struct scull_qset));
}
qs = qs->next;
continue;
}
return qs;
}
continue;有什么作用
正如注释所说的: 是不断的跟随双向链表到底!
网友: 本站网友 时间:2009-04-12 09:43:54 IP地址:159.226.139.★
/* Then follow the list */
while (n--) {
if (!qs->next) {
qs->next = kmalloc(sizeof(struct scull_qset), GFP_KERNEL);
if (qs->next == NULL)
return NULL; /* Never mind */
memset(qs->next, 0, sizeof(struct scull_qset));
}
qs = qs->next;
continue;
}
return qs;
}
continue;有什么作用
Blog作者的回复:
正如注释所说的: 是不断的跟随双向链表到底!
去掉continue;依然可以继续循环,continue是多余的???
Tekkaman:
你好,首先向你的工作致敬,我很希望和你一起探讨内核题,
对于 文中提到“我这个实验除了对参数的改变进行实验外,我的一个重要的目的是测试“ module_param_array(TNparam , int , &TNparam_nr , S_IRUGO);”中&TNparam_nr对输入参数数目的限制作用。经过我的实验,表明&TNparam_nr并没有对输入参数的数目起到限制作用。真正起到限制作用的是“static int TNparam[] = {1,2,3,4};”本身定义的大小,我将程序进行修改:”
我作了测试,当insmod hello-param.ko howmany=2 whom="KeKe" TNparam=4,3,2,1,5,时,系统报错
“insmod:error inserting 'paramadd.ko":-1 Invalid parameters
说明&TNparam_nr有对输入参数的数目起到限制作用,
我用的是Fedora8
博主你是我见过的最好的博主了!永远支持你!
man syslog 如下:
NAME
syslog, klogctl - read and/or clear kernel message ring buffer; set
console_loglevel
SYNOPSIS
int syslog(int type, char *bufp, int len);
/* No wrapper provided in glibc */
/* The glibc interface */
#include <sys/klog.h>
int klogctl(int type, char *bufp, int len);
DESCRIPTION
If you need the libc function syslog() (which talks to syslogd(8)),
then look at syslog(3). The system call of this name is about control‐
ling the kernel printk() buffer, and the glibc version is called
klogctl().
The type argument determines the action taken by this function.
Quoting from kernel/printk.c:
/*
* Commands to sys_syslog:
*
* 0 -- Close the log. Currently a NOP.
* 1 -- Open the log. Currently a NOP.
* 2 -- Read from the log.
* 3 -- Read all messages remaining in the ring buffer.
* 4 -- Read and clear all messages remaining in the ring buffer
* 5 -- Clear ring buffer.
* 6 -- Disable printk to console
* 7 -- Enable printk to console
* 8 -- Set level of messages printed to console
* 9 -- Return number of unread characters in the log buffer
* 10 -- Return size of the log buffer
*/
Only command types 3 and 10 are allowed to non-root processes. Type 9
was added in 2.4.10; type 10 in 2.6.6.
The kernel log buffer
The kernel has a cyclic buffer of length LOG_BUF_LEN in which messages
given as arguments to the kernel function printk() are stored (regard‐
less of their loglevel). In early kernels, LOG_BUF_LEN had the value
4096; from kernel 1.3.54, it was 8192; from kernel 2.1.113 it was
16384; since 2.4.23/2.6 the value is a kernel configuration option. In
recent kernels the size can be queried with command type 10.
The call syslog(2,buf,len) waits until this kernel log buffer is
nonempty, and then reads at most len bytes into the buffer buf. It
returns the number of bytes read. Bytes read from the log disappear
from the log buffer: the information can only be read once. This is
the function executed by the kernel when a user program reads
/proc/kmsg.
The call syslog(3,buf,len) will read the last len bytes from the log
buffer (non-destructively), but will not read more than was written
into the buffer since the last "clear ring buffer" command (which does
not clear the buffer at all). It returns the number of bytes read.
The call syslog(4,buf,len) does precisely the same, but also executes
the "clear ring buffer" command.
The call syslog(5,dummy,dummy) executes just the "clear ring buffer"
command. (In each call where buf or len is shown as "dummy", the value
of the argument is ignored by the call.)
The call syslog(6,dummy,dummy) sets the console log level to minimum,
so that no messages are printed to the console.
The call syslog(7,dummy,dummy) sets the console log level to default,
so that messages are printed to the console.
The call syslog(8,dummy,level) sets the console log level to level,
which must be an integer between 1 and 8 (inclusive). See the loglevel
section for details.
The call syslog(9,dummy,dummy) returns the number of bytes currently
available to be read on the kernel log buffer.
The call syslog(10,dummy,dummy) returns the total size of the kernel
log buffer.
The loglevel
The kernel routine printk() will only print a message on the console,
if it has a loglevel less than the value of the variable con‐
sole_loglevel. This variable initially has the value DEFAULT_CON‐
SOLE_LOGLEVEL (7), but is set to 10 if the kernel command line contains
the word "debug", and to 15 in case of a kernel fault (the 10 and 15
are just silly, and equivalent to 8). This variable is set (to a value
in the range 1-8) by the call syslog(8,dummy,value). The calls sys‐
log(type,dummy,dummy) with type equal to 6 or 7, set it to 1 (kernel
panics only) or 7 (all except debugging messages), respectively.
Every text line in a message has its own loglevel. This level is
DEFAULT_MESSAGE_LOGLEVEL - 1 (6) unless the line starts with <d> where
d is a digit in the range 1-7, in which case the level is d. The con‐
ventional meaning of the loglevel is defined in <linux/kernel.h> as
follows:
#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 */
RETURN VALUE
For type equal to 2, 3, or 4, a successful call to syslog() returns the
number of bytes read. For type 9, syslog() returns the number of bytes
currently available to be read on the kernel log buffer. For type 10,
syslog() returns the total size of the kernel log buffer. For other
values of type, 0 is returned on success.
In case of error, -1 is returned, and errno is set to indicate the
error.
ERRORS
EINVAL Bad parameters (e.g., bad type; or for type 2, 3, or 4, buf is
NULL, or len is less than zero; or for type 8, the level is out‐
side the range 1 to 8).
EPERM An attempt was made to change console_loglevel or clear the ker‐
nel message ring buffer by a process without root permissions
(more precisely: without the CAP_SYS_ADMIN capability).
ERESTARTSYS
System call was interrupted by a signal; nothing was read.
(This can be seen only during a trace.)
CONFORMING TO
This system call is Linux-specific and should not be used in programs
intended to be portable.
NOTES
From the very start people noted that it is unfortunate that a system
call and a library routine of the same name are entirely different ani‐
mals. In libc4 and libc5 the number of this call was defined by
SYS_klog. In glibc 2.0 the syscall is baptized klogctl().
SEE ALSO
syslog(3)
COLOPHON
This page is part of release 2.79 of the Linux man-pages project. A
description of the project, and information about reporting bugs, can
be found at http://www.kernel.org/doc/man-pages/.
您好,我是为向您求教才注册的。我现在想以动态分配设备号的方式加载驱动,并建立设备节点。由于是新手,所以好多地方不是很明白。总之,我希望能在驱动加载上就自动建立设备文件节点,方法1:在网上看到好像说是在驱动中用class之类的可以达到这个效果;方法2:希望通过读取/proc/dev得到的消息来建立设备文件节点,但没写过shell脚本,且不知道怎样让它自动运行。希望得到您的提示。谢谢
要自动创建节点的话必须实现:
1、文件系统中mdev或udev
2、驱动中实现class(或是用偷懒点的办法:直接注册misc类)。
刚才申请的帐号居然登录不上,所以只能匿名了,郁闷……
博主,请问一下你的hello模块没什么没写Kconfig文件,我看有的书上说添加模块必须写kconfig文件啊····?请指教,谢谢!
我是在内核外编译模块,不用Kconfig
请问楼主你的程序哪里来的,书上都不全呀?
我的程序是根据《LDD3》的程序修改、增删而成的。
请问测试程序read(sculltest , &buffer2[20-i] , i),write(sculltest , &buffer1[20-i] , i)两个函数与驱动是怎么挂钩,是怎么样一个运行机制?谢谢。
哎……驱动层与用户层的,代码上的联系是怎么样的?说实话,这个驱动我看完了都不知道它能做什么?更不知道测试程序应该怎么写...惭愧啊
所以在学驱动前一定要学一点应用层的东西,写一些应用层的小软件试试,不如驱动是学不下去的。
请问你当初在应用层是如何学习的?谢谢指点。
我看到你也是硬件出身,很期待你对于应用层开发入门的建议。
我是初学者,我按照你提供的程序输入make modules 输出提示:missing separator. Stop.
不管读,还是写,都休眠,然后就卡在那了,动也动不了,大概是什么原因
博主好久没发 新的关于驱动的啦 ,终于来啦 哈哈,激动
博主:
我是初学者,写2440的linux驱动时会用到一些例如s3c2410_gpio_setpin()的函数,这些函数的定义在内核的哪个目录下呢?有没有一些系统的函数用法说明啊?
博主:
请教个问题,你在驱动程序IO_irq.c中的函数为int IO_irq_ioctl(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg)
而你在应用程序IO_irq_test.c中调用的if ((code=ioctl( IO_irqtest , IO_IRQ_1 , NULL ) ) < 0) ,没有参数struct inode *inode,能解释下吗?谢谢
哈哈,最近也在学ldd3,每学完一章就来你这儿看一下你的笔记,实在是写得太好了。
我刚学习linux驱动,请问以下问题怎么解决呢?
[root@localhost LinuxDriver]# insmod ./hello.o
./hello.o: kernel-module version mismatch
./hello.o was compiled for kernel version 2.4.20
while this kernel is version 2.4.20-8.
你编译模块使用的内核版本和运行模块的内核版本不同,建议统一下。
或者,好像在内核配置上可以关闭这个检查。 |
|