最近在研究内核,主要使用printk来跟踪函数的调用过程。但直接使用printk来打印的话,各种信息太多太杂。而且又不想把已经加了的东西删除。于是决定使用打印等级的方式来实现不同各类信息的显示。

思路很简单,使用不同的宏控制打印函数。打印哪些各类的调试信息由用户控制。通过echo方式传递至内核,实际上是32位的数值,每个比特表示一个各类的信息。因此最多有32种,目前看应该是足够了。为了方便查看哪个比特表示哪种打印,同时为了尽量减小添加代码的麻烦,使用了较多宏定义的技巧。

头文件:

// Add by Late Lee 2016.11.15
extern int g_ll_debug;
enum ll_debug_level{
D_NETCARD = 0, // 网卡层
D_LINK, // 链路层
D_IP, // IP层
D_ICMP, // ICMP
D_ARP,  // ARP
D_UDP,  // UDP
D_TCP,  // TCP
D_SOCKET, // socket通路调试
D_PACKET, // AF_PACKET调试
D_IEEE80211, // 无线调试
// more...
D_VERBOSE = 31,
D_MAX_LEVEL,
};
struct ll_debug__info_t{
const char* name;
int bit;
};
extern const struct ll_debug__info_t ll_debug_info[D_MAX_LEVEL];
#define __ll_debug(level, format, ...)      \
do {                                \
if (unlikely(g_ll_debug&ll_debug_info[level].bit))      \
printk(KERN_ERR "[LL %s %d] " format, __func__, __LINE__, ## __VA_ARGS__);    \
} while (0)
// End

实现代码:

//
// <<<<<<<<<<<<<--- my debug Add by Late Lee 2016.11.15
#define PROC_FILE  "lldebug"
#define _BIT(x) (1<<x)
#define __DEFINE_LEVEL(name) [name] = {#name, _BIT(name)}
const struct ll_debug__info_t ll_debug_info[D_MAX_LEVEL] = {
__DEFINE_LEVEL(D_NETCARD),
__DEFINE_LEVEL(D_LINK),
__DEFINE_LEVEL(D_IP),
__DEFINE_LEVEL(D_ICMP),
__DEFINE_LEVEL(D_ARP),
__DEFINE_LEVEL(D_UDP),
__DEFINE_LEVEL(D_TCP),
__DEFINE_LEVEL(D_SOCKET),
__DEFINE_LEVEL(D_PACKET),
__DEFINE_LEVEL(D_IEEE80211),
__DEFINE_LEVEL(D_VERBOSE),
};
EXPORT_SYMBOL(ll_debug_info);
static int my_debug_proc_show(struct seq_file *m, void *v)
{
int i = 0;
seq_printf(m, "debug info control.\nusage: echo 0xXXX > /proc/%s\n", PROC_FILE);
seq_printf(m, "current debug level: 0x%08x max debug level type: %d\n", g_ll_debug, D_MAX_LEVEL);
for (i = 0; i < D_MAX_LEVEL; i++)
{
seq_printf(m, "bit 0x%02x %s\n", ll_debug_info[i].bit, ll_debug_info[i].name);
}
return 0;
return 0;
}
static int my_version_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, my_debug_proc_show, NULL);
}
static ssize_t my_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_ops)
{
unsigned char buffer[32] = {0};
int value = 0;
if (copy_from_user(buffer, buf, (count > 32 ? 32: count)))
goto out;
value = simple_strtol(buffer, NULL, 16);
g_ll_debug = value;
out:
return count;
}
static const struct file_operations my_debug_proc_fops = {
.open      = my_version_proc_open,
.read      = seq_read,
.write     = my_write,
.llseek    = seq_lseek,
.release   = single_release,
};
struct proc_dir_entry* my_proc_entry = NULL;
void create_debugproc(void)
{
if (!my_proc_entry)
my_proc_entry = proc_create(PROC_FILE, 0, NULL, &my_debug_proc_fops); // 在/proc目录下创建
}
void delete_debugproc(void)
{
if (my_proc_entry)
proc_remove(my_proc_entry);
}
// >>>>>>>>>>>>>>>>>>>>>>>>>>>.

如需要新加调试类型,则在枚举类型ll_debug_level后添加,同时还要在ll_debug_info结构体中定义。

使用

1、在初始化时调用create_debugproc注册到/proc目录。

2、在需要打印调试信息处调用__ll_debug宏定义即可。如__ll_debug(D_IEEE80211, "XXX");

3、将不同数值写到/proc/lldebug文件。数值可组合,如echo 0x28 > /proc/igbdebug表示同时打印ICMP和UDP的调试信息。

下面是所有调试信息等级的说明:

latelee@latelee:~# cat /proc/lldebug
debug info control.
usage: echo 0xXXX > /proc/lldebug
current debug level: 0x00000200 max debug level type: 32
bit 0x01 D_NETCARD
bit 0x02 D_LINK
bit 0x04 D_IP
bit 0x08 D_ICMP
bit 0x10 D_ARP
bit 0x20 D_UDP
bit 0x40 D_TCP
bit 0x80 D_SOCKET
bit 0x100 D_PACKET
bit 0x200 D_IEEE80211
bit 0x00 (null)
bit 0x00 (null)
...
bit 0x80000000 D_VERBOSE

李迟 2016.11.15 夜

一个内核调试函数的实现相关推荐

  1. linux检查是否有D进程,Linux内核调试技术——进程D状态死锁检测

    Linux的进程存在多种状态,如TASK_RUNNING的运行态.EXIT_DEAD的停止态和 TASK_INTERRUPTIBLE的接收信号的等待状态等等(可在include/linux/sched ...

  2. 开源项目-基于Intel VT技术的Linux内核调试器

    本开源项目将硬件虚拟化技术应用在内核调试器上,使内核调试器成为VMM,将操作系统置于虚拟机中运行,即操作系统成为GuestOS,以这样的一种形式进行调试,最主要的好处就是调试器对操作系统完全透明.如下 ...

  3. Linux内核调试 - 一般人儿我都不告诉他(一)【转】

    转自:http://www.cnblogs.com/armlinux/archive/2011/04/14/2396821.html 悄悄地进入Linux内核调试(一) 本文基址:http://blo ...

  4. linux内核调试技术 kprobe使用与实现

    Linux kprobes调试技术是内核开发者们专门为了便于跟踪内核函数执行状态所设计的一种轻量级内核调试技术.利用kprobes技术,内核开发人员可以在内核的绝大多数指定函数中动态的插入探测点来收集 ...

  5. 使用WinDbg内核调试

    WINDOWS调试工具很强大,但是学习使用它们并不容易.特别对于驱动开发者使用的WinDbg和KD这两个内核调试器(CDB和NTSD是用户态调试器). 本教程的目标是给予一个已经有其他调试工具使用经验 ...

  6. 内核调试相关变量说明

    KdInitSystem 函数让内核调试引擎初始化 KiDebugRoutine 当系统分发异常时会调用KiDebugRoutine变量所指向的函数 KiDebugRoutine写入函数地址KdpSt ...

  7. 基于IntelVt技术的Linux内核调试器 - 2

    4 基于IntelVt技术的Linux内核调试器- 调试器设计与实现(2):调试核心 4.1反汇编引擎 如果说调试框架是一个调试器的灵魂,那么接口与反汇编引擎就是一个调试器的身体.我们在调试过程中是要 ...

  8. 内核调试和系统调用劫持

    如何在不重新编译内核,不rmmod内核模块的情况下修改系统调用 为了解决这个问题,最终实现了两种解决方式: 1.Linux系统调用劫持 2.Kprobes内核调试技术(并非真正的修改) 下面分别说下: ...

  9. Windbg内核调试之四: Dump文件分析

    Dump 文件分析很大程度上就是分析蓝屏产生的原因.这种系统级的错误算是Windows提示错误中比较严重的一种(更严重的还有启动黑屏等硬件或软件兼容性错误等等).说它是比较严重,是因为毕竟Window ...

最新文章

  1. java中正则全局匹配_JS中正则表达式全局匹配模式/g用法实例
  2. 【Machine Learning实验5】SVM实验
  3. 声呐图像数据集_MaskedFace-Net 口罩人脸基准数据集,13万+图像数据
  4. 刚接触git,提交文件时,遇到no changes added to commit
  5. 大话设计模式-策略模式与简单工厂模式
  6. MySQL笔记-免密码登录小技巧(运行参数填写skip-grant-tables)
  7. PHP5.3, PHP5.4, PHP5.5新特性
  8. Android 系统(132)---ODM 开发用户常见需求文档(六)
  9. Leetcode每日一题:141.linked-list-cycle(环形链表)
  10. 蓝桥杯2019年第十届C/C++省赛B组第九题-后缀表达式
  11. 深度linux系统硬件要求,国产操作系统Deepin Linux(深度系统)安装体验
  12. python类和对象
  13. 定义一个 Room 类,包含成员变量面积和高度,以及内部类 Table 和 Chair
  14. ubuntu 安装 SMPlayer
  15. Photoshop2019 系统错误 无法启动此程序修复教程
  16. Java获取访问者真实的IP地址
  17. NAO机器人——编程基础
  18. waymo数据集总结
  19. 在Eclipse中配置CheckStyle
  20. PHP安装阿里云消息服务MNS的SDK

热门文章

  1. 马斯克称面临巨大通胀压力 暗示特斯拉可能涨价
  2. 美图影像节发布六款新品 满足用户生活、工作全方位变美需求
  3. 工信部拟规定基本功能软件外的预置App均可卸载
  4. 欧拉好猫车主公开信:宣传部对员工学历没有要求么?
  5. 极兔正式入股百世快递
  6. 俞敏洪直播:最近读了不少关于苏东坡的书
  7. 一台手机苹果含泪赚4000?iPhone 12硬件成本曝光
  8. 阿里云建成全国最大数据中心集群 全面应用自研硬核技术
  9. 微博办公李国庆:急招副总裁,提请股权激励,希望俞渝同意
  10. 日产汽车宣布已关停日、英、美、南非、俄等地工厂