官术网_书友最值得收藏!

Using the strace(1) command-line utility

The strace(1) command-line utility allows you to trace system calls and signals. As strace(1) is not available on Mac machines, this section will use a Linux machine to showcase strace(1). However, as you will see in a later, macOS machines have the dtrace(1) command-line utility that can do many more things.

The number after the name of a program refers to the section of the manual its page belongs to. Although most of the names can be found only once, which means that putting the section number is not necessary, there are names that can be located in multiple sections because they have multiple meanings, such as crontab(1) and crontab(5). Therefore, if you try to retrieve such a page without specifically stating the section number, you will get the entry in the section of the manual that has the smallest section number.

To get a good sense of the output generated by strace(1), look at the following figure where strace(1) is used to examine the executable of addCLAImproved.go:

Using the strace(1) command on a Linux machine

The really interesting part of the strace(1) output is the following line, which cannot be seen in the preceding figure:

$ strace ./addCLAImproved 1 2 2>&1 | grep write
write(1, "Sum: 3\n", 7Sum: 3

We used the grep(1) command-line utility to extract the lines that contain the C system call that interests us, which in this case is write(2). This is because we already know that write(2) is used for printing output. So, you learned that in this case, a single write(2) C system call is used for printing all of the output on the screen; its first parameter is the file descriptor, and its second parameter is the text you want to print.

Note that you might want to use strace(1) with the -f option in order to also trace any child processes that might get created during the execution of a program.

Bear in mind that there exist two more variations of write(2), named pwrite(2) and writev(2), which offer the same core functionality as write(2) but in a slightly different way.

The following variation of the previous command requires more calls to write(2) because it generates more output:

$ strace ./addCLAImproved 1 a b 2>&1 | grep write
write(1, "Ignoring a\n", 11Ignoring a
write(1, "Ignoring b\n", 11Ignoring b
write(1, "Sum: 1\n", 7Sum: 1
Unix uses file descriptors, which are positive integer values, as an internal representation for accessing all its files. By default, all Unix systems support three special and standard filenames: /dev/stdin, /dev/stdout, and /dev/stderr. They can also be accessed using file descriptors 0, 1, and 2, respectively. These three file descriptors are also called standard input, standard output, and standard error, respectively. Additionally, the file descriptor 0 can be accessed as /dev/fd/0 on a Mac machine and as /dev/pts/0 on a Debian Linux machine because everything in Unix is a file.

So, the reason for needing to put 2>&1 at the end of the command is to redirect all of the output, from standard error (file descriptor 2) to standard output (file descriptor 1), in order to be able to search it using the grep(1) command, which searches standard output only. Note that there exist many variations of grep(1), including zegrep(1), fgrep(1), and fgrep(1), that might work faster when they have to deal with large or huge text files.

What you can see here is that even if you are writing in Go, the generated executable uses C system calls and functions because apart from using machine language, C is the only way to communicate with the Unix kernel.

主站蜘蛛池模板: 探索| 长白| 长白| 尉氏县| 永德县| 兴宁市| 鄢陵县| 鄄城县| 吉首市| 麻城市| 浦东新区| 永修县| 应用必备| 右玉县| 仪陇县| 潜山县| 沈阳市| 巴林右旗| 伊宁市| 台东市| 和田市| 故城县| 徐闻县| 马关县| 江西省| 农安县| 镇坪县| 岳池县| 双江| 吴江市| 会昌县| 镇赉县| 德保县| 阳东县| 沧州市| 旺苍县| 清远市| 阿合奇县| 铜鼓县| 桃园县| 偏关县|