内核编码与调试小结

内核模块编码流程:

代码实现:

<1>、包含头文件:

#include <linux/init.h>

#include <linux/module.h>

#include <linux/kernel.h>

……

<2>、模块许可声明:

MODULE_LICENSE("GPL");

<3>、其他函数模块

……

<4>、模块加载函数

static int mqx_init(void)

{

……

return 0;

}

<5>、模块卸载函数

static void mqx_exit(void)

{

……

}

<6>、模块注册

module_init(mqx_init);

module_exit(mqx_exit);

<7>、可选

MODULE_AUTHOR("maqingxiang");

MODULE_DESCRIPTION("This is a ****** module! ");

MODULE_ALIAS("A simplest example");


makefile实现(通用模板):

obj-m += mqx.o

#generate the path

CURRENT_PATH:=$(shell pwd)

#the current kernel version number

LINUX_KERNEL:=$(shell uname -r)

#the absolute path

LINUX_KERNEL_PATH:=/usr/src/linux-headers-$(LINUX_KERNEL)

#complie object

all:

make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules

#clean

clean:

make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean

注:make前面一定是Tab

附:Makefilehttp://bbs.chinaunix.net/thread-1950588-1-1.html

        http://www.cpplive.com/html/1776.html


具体实现:

<1>make 编译模块

<2>insmod mqx.ko 加载模块

<3>dmesg 观察结果(信息在内核日志中)

<4>lsmod 观察内核模块

<5>rmmod mqx 卸载模块

注:用户的切换:su,退出:exit!而用户态执行程序:./test


Gcc编译过程:

对于某个.c文件,我们通常一步到位进行编译,即:gcc *.c -o *

其实gcc编译过程分为4个阶段,即预处理(pre-processing)、编译(compiling)、汇编(assembling)、链接(linking)

详细介绍——>

1、预处理阶段:gcc -E *.c -o *.i

输入.c文件,输出.i文件;在此阶段源文件(*.c)和相应的包含文件(*.h)一起进行预处理,对#define#ifdef#include等预编译指令进行解析(宏替换、注释消除、加载库文件)。

2、编译阶段:gcc -S *.i -o *.s(汇编语言文件)

输入.i的中间文件,输出.s的汇编语言文件

3、汇编阶段:gcc -c *.s -o *.o(目标文件)

输入.s的汇编语言文件,输出.o的二进制机器代码文件

4、链接阶段:gcc *.o -o *(可执行文件)

输入.o的二进制代码文件,连同其他的(如果有的话)机器代码文件和库文件一起汇集成一个可执行的二进制代码文件。

其格式如下:

gcc [option] [filename]
复制代码
-x language  指定使用的语言

-c       对文件进行编译和汇编,但不进行连接

-S       对文件进行编译,但不汇编和连接

-E       仅对文件进行预处理

-o       编译成可执行文件

-wall     显示附加的警告信息

-g       显示错误信息以便调试(调试标记)
  
-O1/O2/O3   对代码进行优化,数字越大优化等级越高

-v       查看gcc版本

附:其它一些GNU工具

1、怎么查明可执行映像或是中间目标文件的大小呢?

答:size工具可以给出text大小(指令和常量)、data段、bss段。命令为:

$ size test.o

2、希望得到有关映像的更详细的信息,怎么办呢?

答:可以使用objdump工具,加上-syms参数使用objdump工具可以得到映像文件或目标文件中的符号列表,包括它们的类型(textbssdata)、长度、偏移等信息。命令为:

$ objdump -syms test.o

使用参数-disassemble来进行反汇编映像文件到自然指令集合,此命令将列出在目标文件中找到的函数,以及GCC为这些函数分别生成的指令。命令为:

$ objdump -disassemble test.o


Gdb调试过程:

首先在编译时,必须把调试信息加入到可执行文件中,使用gcc-g参数可以做到这一点。

最常用的调试命令:

gdb test ----------------------------------------启动gdbtest为执行文件,一般在当前目录下

q----------------------------------------------------退出gdb

查看源码:

l----------------------------------------------------相当于list,从第一行开始列出源码

list -----------------------------------------------显示上次列出源码的前十行,类似于向上翻页

enter---------------------------------------------直接回车,表示重复上一次命令

directory DIR--------------------------------新增一个路径到源码搜索路径

设置中断点:

break num-------------------------------------设置断点,num为行号

break func-------------------------------------设置断点,在函数func()入口处

info break--------------------------------------查看断点信息

delete number-------------------------------删除指定编号的中断点

disable number------------------------------使指定编号的中断点失效

enable number-------------------------------取消disable,使指定编号的中断点生效

程序执行:

r----------------------------------------------------相当于run,运行程序

n----------------------------------------------------相当于next,单条语句执行,step over

c----------------------------------------------------相当于continue,离开中断点,继续执行命令

until-----------------------------------------------离开forwhile等循环

finish---------------------------------------------继续执行程式,直到函数返回

k---------------------------------------------------终止程序执行

变量检查:

p i--------------------------------------------------相当于print,打印变量i的取值

whatis--------------------------------------------识别数组或变量的类型

ptype----------------------------------------------提供结构体的定义

bt---------------------------------------------------查看函数堆栈,backtrace

Multi-thread

info threads------------------------------------显示目前所有的thread

thread thread_num-------------------------切换GDB到指定的thread_num

改变程序执行行为:

return---------------------------------------------直接从程序当前执行位置返回,放弃未执行部分

return expression----------------------------执行return,并返回exprssion的值

set arname=xxx------------------------------更改变量值


 多进程应用程序调试:

可以使用follow-fork-mode child/parent 命令告诉GDB返回到哪一个并跟随它,GDB跟随其中一个进程,另一个进程则会不受阻碍地继续运行。还可以告诉GDB在出现fork后询问要跟随哪一个进程,命令为:set follow-fork-mode ask


 多线程应用程序调试:

1、如果把断点设置在源程序的某一行,而这一行又被多个线程调用,那么每一个调用它的线程都会被影响。这明显不是我们想要的结果,那么怎么解决呢?

答:可以通过指定会被影响的线程来限制这种情况,即设置断点时可以指定会被影响的线程:break test.c : 5 thread 5 (if 条件)

可以使用命令info threads列出所以活动的线程和它们当前的状态。某线程前面的*说明它是调试器当前关注的线程;可以命令thread换到任何一个线程,即可让调试器关注的线程改为指定线程。

2、逐步运行多线程应用程序时,会发现调试器关注的线程每一步都可能变化,当我们对当前线程特别感兴趣时往往会很烦人,那么怎么解决呢?

答:可以通过锁定调度器来命令GDB不要自行根据优先权来改变当前线程,命令为:gdbset scheduler - locking on

如果希望允许比当前更优先的线程,可以把上面设置的模式关掉,命令为:

gdbset scheduler - locking off

我们还可以使用show命令来确定当前模式,命令为:

gdbshow scheduler – locking

3、如果我们希望对所有的线程应用一个命令,那么如何解决呢?

答:命令thread apply all就用于向所有线程应用同一个命令,例如:

gdbthread apply all backtrace (让所有的活动线程发回栈回溯)

命令thread apply还可以对几个指定的线程列表应用命令,例如:

gdbthread apply 1 4 9 backtrace(显示第149号线程的栈回溯)


 调试已有的进程:

对于一个正在运行的应用程序,可以把GDB挂接到它的进程进行调试,这里只需要知道这个需要调试的进程的识别符。启动GDB后,使用命令attach挂接到指定进程,将进程挂起,进行控制它。完成调试后,可以使用命令detach与进程脱离,让进程继续运行。

注:这种方法非常适用于处理那些运行一段时间后没有响应的程序,也适用于处理实际运行环境中意外地无法响应的程序。


 事后分析调试:

segmentation fault core dumped)或者总线错误,内核文件已转储

应用程序异常结束并转储内核转储文件时,可以使用GDB来确定到底发生了什么。

注:要激活DNU/Linux生成内核转储,应该执行限制解除命令 ulimit -c 。否则,在有这个限制时,不会生成内核转储文件。

先执行应用程序,得到内核转储文件。

$ ./test

segmentation fault core dumped

$ ls

core.12345 test test.c

把应用程序可执行映像和内核转储文件都提供给GDB

# gdb test core.12345

GDB加载应用程序,然后用内核转储文件来确定在运行错误时发生了什么。(在加载完所有的符号后,可以看到失败发生在哪个函数中;更进一步地,可以看到那个引起错误的调用,这一条语句是为了进行内核转储添加的。)


 利用core file排错:

当程序产生segmentation fault时,系统会将当时的所有状态,包括变量值,记忆体资料以及程序中各个函数的呼叫状态dump成一个core file。我没可以用GDB来读取core file,分析当时引起segmentation fault的原因。

@编译gcc -g test.c -o test

@$ gdb ./test core

@设置core file 最大szie:其预设值为0,用命令$ ulimit -c unlimited改成没有限制。

@执行程序:./test

@利用bt找出发生错误的地方

@利用list *ADDRESS列出产生错误的程序代码

@利用print ptr观察变量值



参考网站:

附:GDB调试手册:

http://www.cmlab.csie.ntu.edu.tw/~daniel/linux/gdb.html

http://baike.baidu.com/view/639266.htm

http://www.programlife.net/gdb-manual.html

http://www.cnblogs.com/shipfi/archive/2008/08/04/1260293.html

gdb学习笔记:(在看中...)——强力推荐

http://yaronspace.cn/blog/archives/tag/gdb

调试内核:(在看中...

http://blog.csdn.net/jiayanhui2877/article/details/4452960

http://www.ibm.com/developerworks/cn/linux/l-kdb/#iratings

http://www.ibm.com/developerworks/cn/linux/l-kdbug/index.html

http://www.ibm.com/developerworks/cn/linux/l-kprobes.html







原文地址:https://www.cnblogs.com/xymqx/p/3435151.html