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

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.

主站蜘蛛池模板: 宜良县| 寿光市| 容城县| 尉氏县| 抚顺县| 馆陶县| 云浮市| 鹤壁市| 临城县| 诸城市| 永胜县| 嫩江县| 汕尾市| 武安市| 桐乡市| 囊谦县| 永康市| 三台县| 聂拉木县| 新乡县| 潜江市| 新和县| 静海县| 汾西县| 阿克陶县| 安化县| 晋宁县| 东莞市| 梁山县| 甘南县| 库尔勒市| 神木县| 阿克苏市| 宜州市| 阜阳市| 庐江县| 子长县| 平塘县| 枣庄市| 云霄县| 留坝县|