Linux字符设备驱动学习(4)——内核调试

一、内核开发的配置选项

1.CONFIG_DEBUG_KERNEL
该选项仅仅使得其他的调试选项可以。我们应该打开该选项,但它本身不会打开所以的调试功能。

2.CONFIG_DEBUG_SLAB
这是一个非常重要的选项,他打开内核内存分配函数中的多个类型检查:打开该检查后,就可以检测许多内存溢出忘记初始化的错误。在将已分配内存返回给调用者之前,内核将把其中的每个字节设置为0xa5,而在释放后将其设置为0x6b。可在自己去的程序的输出或用过在oops信息中看字符判断问题所在。在打开调试选项后,内核还会在每个已分配内存对象的前面或后面防止特殊防护值。这样,当防护值发生改变是,内核就可以知道有些代码超出了内存的正常访问范围,并警报。

3.CONFIG_DEBUG_PAGELLOC
在释放时,全部内存页从内核地址空间移出。该选项大大降低了运行速度,但可以快速定位特定的内存损坏错误的所在位置。

4.CONFIG_DEBUG_SPINLOCK_SLEEP
该选项将检查用于自旋锁时的休眠企图。若调用可能引起休眠的函数,这个选项也会生效,即使该函数可能不会导致真正的休眠。

5.CONFIG_INIT_DEBUG
标记为_ init(或 _initdata)的符号将会在系统初始化或模块装载后被丢弃。该选项用来检查初始化后对于初始化的内存空间的访问企图

6.CONFIG_DEBUG_INFO
该选项使内核的构造包含完整到的调试信息。若用gdb调试内核,则需要这些消息,当使用gdb时,还需要打开CONFIG_FRAME_POINTER选项。

7.CONFIG_DEBUG_STACKOVERFLOW || CONFIG_DEBUG_STACK_USAGE
这些选项可帮助跟踪内核栈的溢出问题。栈溢出的确切信号是不包含任何合理的反向跟踪信息的oops清单。第一个选项将在内核中增加明确的溢出检查。第二个选项将让内核监视栈的使用,并通过SysRq按键输出一些统计信息。

8.CONFIG_KALLSYMS
该选项出现在General setup/Standard features菜单中,将在内核中包含符号信息。该选项默认是打开的,该符号信息用于调试上下文

9.CONFIG_IKCONFIG || COFIG_IKCONFIG_PROC
这些选项出现在General setup菜单中,会让完整的内核配置状态包含到内核中,可通过/proc访问。

10.CONFIG_ACPI_DEBUG
该选项出现在Power management/ACPI菜单中。该选项在打开ACPI(Advanced Configuration and Power Interface,高级配置和电源接口)中的详细调试信息。

11.CONFIG_DEBUG_DRIVER
在Device drivers菜单中,该选项打开驱动程序核心中的调试信息,帮助追踪底层支持代码中的问题。

12.CONFIG_SCSI_CONSTANTS
该选项出现在Device drivers/SCSI device support菜单中,它将打开详细的SCSI错误信息

13.CONFIG_INPUT_EVBUG
该选项在Device drivers/Input device support中找到,它会打开对输入事件的详细记录。若要求针对输入设备编写驱动程序,则可以使用该选项。该选项会记录键入的任何东西,会导致安全问题。

14.CONFIG_PROFILING
该现象可在Profiling support(剖析支持)菜单中找到,剖析通常用于系统性能的调节,但对跟踪内核挂起及相关问题也会有所帮助。

二、通过打印调试

调试内核代码是,利用printk来完成调试。
printk可以通过附加不同的日志级别,或者消息优先级来根据这些级别锁表示的严重程序对消息进行分类。

在编译时将表示日志级别的宏和消息文本拼接在一起,无逗号。
例如:

调试信息:
	    printk(KERN_DEBUG "Here I am:%s:%i\n",_ _FILE _ _, _ _LINE _ _);
临界信息:
		printk(KERN_CRIT "I'm trashed; giving up on %p\n",ptr);

八种可用的日志级别字符串:
1.KERN_EMERC
用于紧急事件消息,一般是系统崩溃前的提示信息。

2.KERN_ALERT
用于需要立即采取动作的情况。

3.KERN_CRIT
临界状态,通常涉及严重的硬件或软件操作失败

4.KERN_ERR
用于报告错误状态。设备驱动程序会经常使用KERN_ERR来报告来自硬件的问题。

5.KERN_WARNING
对可能出现的情况进行警告,但着了情况通常不会对系统造成严重问题。

6.KERN_NOTICE
有必要进行提示的正常情况。许多与安全相关的状况用这个级别进行汇报。

7.KERN_INFO
提示性信息,很多驱动程序在启动的时候以这个级别来打印出它们找到的硬件信息。

8.KERN_DEBUG
用于调试信息

三、重定向控制台消息

内核可以将消息发送到一个指定的虚拟控制台。控制台就是当前的虚拟终端,可以在任何一个控制台设备上调用ioctl(TIOCLINUX)来指定接收消息的其他虚拟终端。

可选择专门用来接收内核消息的控制台


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/ioctl.h>

int main(int argc, char **argv)
{
    char bytes[2] = {11,0}; /* 11 is the TIOCLINUX cmd number */

    if (argc==2) bytes[1] = atoi(argv[1]); /* the chosen console */
    else {
        fprintf(stderr, "%s: need a single arg\n",argv[0]); exit(1);
    }
    if (ioctl(STDIN_FILENO, TIOCLINUX, bytes)<0) {    /* use stdin */
        fprintf(stderr,"%s: ioctl(stdin, TIOCLINUX): %s\n",
                argv[0], strerror(errno));
        exit(1);
    }
    exit(0);
}

四、消息如何被记录

①printk函数将消息写到一个长度为_ LOG_BUF_LEN字节的循环缓冲区中(在配置内核时为 _LOG_BUF_LEN指定4KB-1KB之间的值)
②唤醒任何正在等待消息的进程(即睡眠在syslog系统调用上的进程),或正在读取/proc/kmsg的进程,dmesg可以不刷新缓冲区。
③停止klogd后读取/proc/kmsg文件会阻塞进程,如果已有klogd或其他进程读取时,不能直接读取该文件,避免竞争。
④缓冲区写满会覆盖,可能丢失旧数据,
⑤klogd读取内核消息发送到syslogd。
⑥syslogd根据/etc/syslog.conf找出处理这些数据的方法。
⑦syslogd根据功能和优先级对消息进行区分。
⑧内核消息由LOG_KERN工具记录,并且与printk中对应的优先级记录,如果没有运行klogd,数据将保留在缓冲区。
⑨klogd-(file)可以只是klogd将消息保存到某个特定文件。

五、开启及关闭消息

全局的开启或禁止调试信息,并对个别消息进行开关控制。

定义一个宏,在需要时,这个宏展开为一个printk调用
在这里插入图片描述
是否定义PDEBUG取决于是否定义SCULL_DEBUG,它能根据代码锁运行额环境来选择合适的方式显示信息。
在内核态时:使用内核调用printk
在用户空间:使用libc调用fprintf,并输出到标准错误设备。
符号PDEBUGG什么也不做,它可将打印语句注释掉,而不必把他们完全删除。
在这里插入图片描述

六、速度限制

问题的产生:利用printk产生上千条消息,从而让日志信息充满控制台,更可能使系统日志文件溢出。若使用慢速控制台设备,过高的消息输出速度会导致系统变慢,甚至时系统无法正常相应。

设置一个标志位来发出警告,并且在该标志位被设置时不在打印任何消息。(避免同一个数据多次发送)

int printk_ratelimit(void);
//通过跟踪发送到控制到的消息数量工作。
  若输出速度超过一个阈值,则返回零。

例子:

//
	在打印一条可能被重复的消息之前,应调用上面函数。若该函数返回一个非零值,
	则可以继续并打印消息,否则跳过。
	
	if(printk_ratelimit()){
		printk(KERN_NOTICE "error\n");
	}

七、打印设备号

//这两个宏均是将设备编号打印到特定的缓冲区。

int print_dev_t(char *buffer, dev_t dev);
返回的是打印的字符数

char *format_dev_t(char *buffer, dev_t dev);
返回的是缓冲区,可直接作为调用printk时的参数使用。

八、通过查询调试

①大量使用printk会显著降低系统性能syslogd试图把每件事都记录到磁盘上
②在/etc/syslogd.conf中日志文件名字前加一个减号可以避免实时刷新磁盘
③获取信息最好的方法是需要的时候才去查询

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux字符设备驱动实验是指在Linux操作系统中编写和测试字符设备驱动程序的过程。字符设备驱动程序负责与字符设备进行交互,包括输入输出数据、控制设备和处理设备的状态等。 在进行Linux字符设备驱动实验之前,首先需要了解字符设备字符设备驱动的基本概念及其工作原理。字符设备是指以字符为单位进行输入输出的设备,如串口、打印机等。字符设备驱动是指将操作系统与字符设备进行交互的程序。 在实验中,我们通常需要编写一个字符设备驱动程序,包括初始化设备、读写数据、控制设备等功能。首先,我们需要定义字符设备驱动的数据结构,包括设备号、驱动程序打开、关闭等函数的实现。然后,我们需要实现字符设备驱动的读写函数来实现数据的输入输出。最后,我们可以进行一些附加功能的实现,如控制设备的状态、处理中断等。 在实验过程中,我们需要使用Linux内核提供的字符设备接口来进行字符设备驱动的编写和测试。可以使用一些工具和命令来加载和测试字符设备驱动程序,如insmod、rmmod等。通过这些工具和命令,我们可以加载和卸载字符设备驱动程序,并在用户空间进行数据的读写操作,来测试字符设备驱动的功能和性能。 Linux字符设备驱动实验可以帮助我们深入了解字符设备字符设备驱动的工作原理,并学习Linux内核的开发和调试技术。通过实验,我们可以更好地理解操作系统和驱动程序之间的关系,提高我们在Linux系统开发和嵌入式系统开发中的能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值