21.8 strace
在Linux系统中,strace是一种相当有效的跟踪工具,strace的主要特点是可以被用来监视系统调用。不仅可以用strace调试一个新开始的程序,也可以调试一个已经在运行的程序(这意味着把strace绑定到一个已有的PID上)。对于第6章的globalmem字符设备文件,以strace方式运行如代码清单21.8所示的用户空间应用程序globalmem_test(使用gcc命令编译globalmem_test.c文件 gcc globalmem_test.c -o test),以strace ./test的方式运行结果如下:
execve("./globalmem_test", ["./globalmem_test"], [/* 24 vars */]) = 0
...
open("/dev/globalmem", O_RDWR) = 3 /* 打开的/dev/globalmem的fd是3 */
ioctl(3, FIBMAP, 0) = 0
read(3, 0xbff17920, 200) = -1 ENXIO (No such device or address)/* 读取失败 */
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f04000
write(1, "-1 bytes read from globalmem\n", 29-1 bytes read from globalmem
) = 29 /* 向标准输出设备(fd为1)写入printf中的字符串 */
write(3, "This is a test of globalmem", 27) = 27
write(1, "27 bytes written into globalmem\n", 3227 bytes written into globalmem
) = 32
...
输出的每一行对应一次Linux系统调用,其格式为“左边=右边”,等号左边是系统调用的函数名及其参数,右边是该调用的返回值。
代码清单21.8 用户空间应用程序globalmem_test
#include ...
#define MEM_CLEAR 0x1
void main(void)
{
int fd, num, pos;
char wr_ch[200] = "This is a test of globalmem";
char rd_ch[200];
/* 打开/dev/globalmem */
fd = open("/dev/globalmem", O_RDWR, S_IRUSR | S_IWUSR);
if (fd != -1 ) { /* 清除globalmem */
if(ioctl(fd, MEM_CLEAR, 0) < 0)
printf("ioctl command failed\n");
/* 读globalmem */
num = read(fd, rd_ch, 200);
printf("%d bytes read from globalmem\n",num);
/ * 写globalmem */
num = write(fd, wr_ch, strlen(wr_ch));
printf("%d bytes written into globalmem\n",num);
...
close(fd);
}
}
使用strace虽然无法直接追踪到设备驱动中的函数,但是足以帮助工程师进行推演:
如从open(“/dev/globalmem”,O_RDWR)=3的返回结果知道/dev/globalmem的fd为3,之后对fd为3的文件进行read()、write()和ioctl()系统调用,最终会使globalmem里file_operations中的相应函数被调用,通过系统调用的结果就可以知道驱动中globalmem_read()、globalmem_write()和globalmem_ioctl()的运行结果。