为什么没有strace记录我的所有系统调用?

时间:2017-02-09 00:51:19

标签: linux debian strace

我正在尝试在运行Debian 8.7的BeagleBone上调试串行连接。为此,我已经编写了一个测试程序。我没有得到我期待的结果,所以我在测试程序中激发了分歧。

果然,我希望看到的写系统调用不在那里。我检查了我的源代码,他们肯定应该在那里。测试程序基本上是这样的:

loop:
   write a log message to stderr
   write a buffer of binary 0x00 to the serial port 
   write a different log message to stderr
   write a buffer of binary 0xff to the serial port 

程序在stderr上产生如下所示的输出:

2015/11/12 21:28:45 111...
2015/11/12 21:28:46 000...
2015/11/12 21:28:48 111...
2015/11/12 21:28:49 000...
2015/11/12 21:28:51 111...
2015/11/12 21:28:52 000...
2015/11/12 21:28:54 111...
2015/11/12 21:28:55 000...
2015/11/12 21:28:57 111...
2015/11/12 21:28:58 000...
2015/11/12 21:29:00 111...
2015/11/12 21:29:01 000...
2015/11/12 21:29:03 111...
2015/11/12 21:29:04 000...
2015/11/12 21:29:06 111...
2015/11/12 21:29:07 000...
2015/11/12 21:29:09 111...
2015/11/12 21:29:10 000...
2015/11/12 21:29:12 111...
2015/11/12 21:29:13 000...
2015/11/12 21:29:15 111...
2015/11/12 21:29:16 000...
2015/11/12 21:29:18 111...
2015/11/12 21:29:19 000...
2015/11/12 21:29:21 111...

然后我观察到并非所有对stderr的写入都出现在strace输出中。将会有第一条日志消息的运行而没有任何第二条消息,这在上面的算法中是不可能发生的。这是输出的摘录,通过grepping trace.log进行过滤以进行写入。正如您所看到的,strace条目比stderr中的行少得多,表明strace没有记录实际正在进行的所有系统调用。

write(2, "2015/11/12 21:28:46 000...\n", 27) = 27
write(2, "2015/11/12 21:28:49 000...\n", 27) = 27
write(2, "2015/11/12 21:28:52 000...\n", 27) = 27
write(2, "2015/11/12 21:28:55 000...\n", 27) = 27
write(2, "2015/11/12 21:28:58 000...\n", 27) = 27
write(2, "2015/11/12 21:29:01 000...\n", 27) = 27
write(2, "2015/11/12 21:29:04 000...\n", 27) = 27
write(2, "2015/11/12 21:29:07 000...\n", 27) = 27
write(2, "2015/11/12 21:29:12 111...\n", 27) = 27
write(2, "2015/11/12 21:29:15 111...\n", 27) = 27
write(2, "2015/11/12 21:29:18 111...\n", 27) = 27
write(2, "2015/11/12 21:29:21 111...\n", 27) = 27

我的源代码或我正在使用的任何go库中没有并发,没有任何子进程的分支。

我检查了strace手册页,似乎没有任何方法可以指定系统调用的统计抽样,也没有任何迹象表明它不会记录所有这些,除非你指定了一个过滤表达式(我没有)。

我不知道是否实际发生了针对串口的写系统调用,但是现在我不能相信strace输出,因为它没有向我显示我所知道的所有系统调用。

有人可以解释发生了什么吗?

我的命令行是:

strace -o trace.log -v ./serial-test --device /dev/ttyO2 --oscillator --delay 500

更新:朋友建议添加一个似乎有帮助的-f标志。不清楚的是为什么,因为文档建议-f仅在调用fork()时才有用,并且我的程序中没有(或者实际上,在strace输出中)。

好的,因此,联机帮助页也引用了clone(),并且使用clone()创建了Linux线程。 go使用Linux线程,所以这解释了这个问题。

1 个答案:

答案 0 :(得分:3)

这归结为golang自由使用线程这一事实,因此您需要使用strace -f标志来跟踪代表您创建的辅助线程。

因此,strace -f系统调用创建的子进程以及fork() [和clone()]创建的线程都需要vfork()标志。我的错误是认为它只是儿童过程所必需的。