1. Abstract
.
2. Introduction
我们开发的时候很痛苦的一件事情就是在进程进入深睡眠以后,没有调试手段,往往这种问题还都是一些很难解的概率性难题,而此时又不知道这个进程到底在什么地方深睡眠了。
针对此问题,我开发了相应的驱动(请参考文章后附录的完整源代码)和应用 tool ,大家使用该方法就能够将一个进程的函数调用关系打印出来,于是假设一个进程深睡眠了,大家就可以得知它到底死在什么地方了。
3. 定位工具使用方法
3.1 准备
使用之前要先加载驱动和设备节点:
insmod getstack.ko
mknod /dev/getstack c 251 0
注:请通过如下命令 cat /proc/devices ,来查看 getstack 在你的板子上所对应的字符设备的 Major 号。
3.2 使用方法
我开发了一个应用程序 tool ,大家可以直接调用,方法如下:
./getstack --help
Usage: [options] pid/name
Options:
-p |--pid Print the stack of process with process's id.
-n |--name Print the stack of process with process's name.
-a |--all Print the stack of all processes.
--daemon Fork and go into the background.
--quiet Do not print anything.
--help Print this help message.
如果要看某个进程当前的内核函数调用堆栈,可以用 ps 得到其 pid ,然后调用 ./getstack -p pid 即可。
如果要查看所有进程的内核函数调用堆栈,调用 ./getstack –a
-n 我试了一下还不行,当前还没有跟踪原因,因为 -n 可以被 -p 取代,所以我也不想再跟踪了。
4. 原理分析
4.1 定位工具tool
这个工具的原理很简单,就是调用驱动的相应接口,辅助的代码都被我省掉了:
……
void getstack_finalize()
{
int gs_result;
if(gs_fd < 0)
{
printf("fd is not opened!/n");
return;
}
gs_result = close(gs_fd);
printf("getstack_finalize want to close fd: %d, and result is: %d/n", gs_fd, gs_result);
gs_fd = -1;
}
int getstack_showall(void)
{
if (ioctl(gs_fd, PRINT_ALL_TASK, NULL) < 0) {
printf("ioctl PRINT_STACK/n");
return -1;
}
return 0;
}
int getstack_pid(int pid)
{
if (ioctl(gs_fd, PRINT_PID_TASK, &pid) < 0) {
printf("ioctl PRINT_STACK/n");
return -1;
}
return 0;
}
int getstack_pname(char * pname)
{
if (ioctl(gs_fd, PRINT_PNAME_TASK, pname) < 0) {