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

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.

主站蜘蛛池模板: 浦北县| 顺昌县| 宝兴县| 靖江市| 阿拉善盟| 含山县| 大兴区| 碌曲县| 卫辉市| 高平市| 蒙自县| 芒康县| 平陆县| 伊宁市| 七台河市| 绿春县| 尤溪县| 徐州市| 穆棱市| 磐安县| 文化| 宿松县| 乐都县| 同仁县| 唐海县| 民乐县| 乐东| 务川| 铜川市| 麟游县| 托克托县| 自贡市| 叙永县| 文山县| 南平市| 左权县| 庆城县| 塔城市| 策勒县| 华坪县| 蓝田县|