Linux设备驱动程序学习(2)-调试技术
来源:互联网 发布:学生化妆品知乎 编辑:程序博客网 时间:2024/05/18 02:28
一、内核中的调试支持在前面已经建议过:学习编写驱动程序要构建安装自己的内核(标准主线内核)。最重要的原因之一是:内核开发者已经建立了多项用于调试的功能。但是由于这些功能会造成额外的输出,并导致能下降,因此发行版厂商通常会禁止发行版内核中的调试功能。为了实现内核调试,我在内核配置上增加了几项: 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,定义在中:#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 */ --------------------------------------------------------------------------------而在运行是改变console_loglevel的程序(《Linux设备驱动程序(第3版)》提供)如下: #include #include #include #include #define __LIBRARY__ /* _syscall3 and friends are only available through this */#include /* 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);} 最关键的“syslog(8,NULL,level)”语句我不理解,没有找到相关资料。但是通过在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.koHello, Tekkaman Ninja ![Tekkaman2440@SBC2440V4]#rmmod helloGoodbye, 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/printk1 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/printk7 4 1 7[Tekkaman2440@SBC2440V4]#insmod hello.koHello, Tekkaman Ninja ![Tekkaman2440@SBC2440V4]#rmmod helloGoodbye, Tekkaman Ninja ! Love Linux !Love ARM ! Love KeKe ! 四个数字的含义:当前的loglevel、默认loglevel、最小允许的loglevel、引导时的默认loglevel。 -------------------------------------------------------------------------------- 为了方便的打开和关闭调试信息,《Linux设备驱动程序(第3版)》提供以下源码:/* 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 debuggingDEBUG = y# Add your debugging flag (or not) to CFLAGSifeq ($(DEBUG),y) DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlineselse DEBFLAGS = -O2endifCFLAGS += $(DEBFLAGS) --------------------------------------------------------------------------------为了避免printk重复输出过快而阻塞系统,内核使用以下函数跳过部分输出:int printk_ratelimit(void); 典型的应用如下: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的行为。 -------------------------------------------------------------------------------- Linux还提供了打印设备编号的宏(在中定义):int print_dev_t(char *buffer, dev_t dev);char *format_dev_t(char *buffer, dev_t dev); 两个函数的唯一区别是:print_dev_t返回打印字符数,format_dev_t返回缓冲区指针。注意缓冲区char *buffer的大小应至少有20B。--------------------------------------------------------------------------------三、通过查询调试多数情况中,获取相关信息的最好方法是在需要的时候才去查询系统信息,而不是持续不断地产生数据。使用/proc文件系统/proc文件系统是一种特殊的、由软件创建的文件系统,内核使用他向外界导出信息。/proc下面的每个文件都绑定于一个内核函数,用户读取其中的文件时,该函数动态的生成文件的内容。如以前用过的:[Tekkaman2440@SBC2440V4]#cat /proc/devicesCharacter 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 mtd116 alsa128 ptm136 pts180 usb189 usb_device204 s3c2410_serial252 scull253 usb_endpoint254 rtcBlock devices: 1 ramdisk256 rfd 7 loop 31 mtdblock 93 nftl 96 inftl179 mmc 使用/proc的模块必须包含,而使用seq_file接口要包含。具体的应用方法看源程序、做实验更有效果。--------------------------------------------------------------------------------至于其他的调试方法,如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_testwrite code=6write code=6write code=6write code=2read code=6read code=6read code=6read 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]#ls1 751 cmdline kallsyms stat2 769 cpu kmsg swaps3 77 cpuinfo loadavg sys4 778 crypto locks sysrq-trigger5 779 devices meminfo sysvipc59 78 diskstats misc timer_list6 781 driver modules tty60 783 execdomains mounts uptime63 785 filesystems mtd version65 79 fs net vmstat707 80 ide partitions yaffs708 819 interrupts scullmem zoneinfo709 asound iomem scullseq710 buddyinfo ioports self742 bus irq slabinfo[Tekkaman2440@SBC2440V4]#cat scullmemDevice 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 scullseqDevice 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]#ls1 742 buddyinfo iomem self2 751 bus ioports slabinfo3 769 cmdline irq stat4 77 cpu kallsyms swaps5 778 cpuinfo kmsg sys59 779 crypto loadavg sysrq-trigger6 78 devices locks sysvipc60 781 diskstats meminfo timer_list63 783 driver misc tty65 785 execdomains modules uptime707 79 filesystems mounts version708 80 fs mtd vmstat709 824 ide net yaffs710 asound interrupts partitions zoneinfo
- Linux设备驱动程序学习(2)-调试技术
- Linux设备驱动程序学习(2)-调试技术
- Linux设备驱动程序学习(2)-调试技术
- Linux设备驱动程序学习(2)-调试技术
- Linux设备驱动程序学习(2)-调试技术
- Linux设备驱动程序学习(2)-调试技术(补充)
- Linux设备驱动程序-调试技术
- 【原创】《Linux设备驱动程序》学习之循序渐进 --- 调试技术
- 《LINUX设备驱动程序》第4章(调试技术)学习笔记
- linux设备驱动程序第二版 调试技术
- 《Linux设备驱动程序》——调试技术
- Linux设备驱动程序(第三版)学习之内核的调试技术(三)_2_查询调试
- Linux设备驱动程序第三版学习(3)- 调试
- Linux设备驱动程序第三版学习(3)- 调试
- Linux设备驱动程序第三版学习(3)- 调试 .
- linux设备驱动程序调试
- Linux设备驱动程式学习(2)-调试技术
- Linux设备驱动程式学习(2)-调试技术
- 给你的应用程序添加动态鼠标
- 轻松实现类VC界面
- 如何获得另一个应用程序窗口中的文本
- Ubuntu .deb包安装方法
- 软件设计原则之依赖倒转原则
- Linux设备驱动程序学习(2)-调试技术
- Effective C# 原则21:用委托来表示回调
- 几个免费下载原版图书的网站收藏
- Flex读取外部XML中文乱码解决办法
- 字符串操作
- Linux网络资源
- 设计原则之迪米特法则
- 清除VS2005中最近工作的项目
- 决心学摄影