# syscall analysis ## Nginx (v1.18.0) 以下為處理單個 HTTP GET request 時發出的系統呼叫: - 以 [Intel Pin](https://software.intel.com/content/www/us/en/develop/articles/pin-a-dynamic-binary-instrumentation-tool.html) 動態觀察系統呼叫的使用: ``` syscall #: 232 syscall #: 288 syscall #: 45 syscall #: 4 syscall #: 257 syscall #: 5 syscall #: 20 syscall #: 40 syscall #: 3 syscall #: 233 syscall #: 54 syscall #: 232 syscall #: 45 syscall #: 3 ``` 對應系統呼叫名稱為: ``` epoll_wait accept4 recvfrom stat openat fstat writev sendfile close epoll_ctl setsockopt epoll_wait recvfrom close ``` - 以 [Intel Pin](https://software.intel.com/content/www/us/en/develop/articles/pin-a-dynamic-binary-instrumentation-tool.html) 動態觀察同樣行為的 call trace: ([Gist 連結](https://gist.github.com/foxhoundsk/1d12f6cad037f28b2cf35887b0c752eb)) 單個 HTTP request 的 call trace 約為 1.1k 行左右...,上述大部份系統呼叫都可以在 call trace 中找到,找不到的可能是用其他 symbol name 包裝了,例如:`fstat`, `stat` 在 glibc 中分別以 `__fxstat64` 以及 `__xstat64` 包裝。 - 以 strace 動態觀察同樣行為: ``` epoll_wait(7, [{EPOLLIN, {u32=1479659536, u64=140236456841232}}], 512, -1) = 1 accept4(5, {sa_family=AF_INET, sin_port=htons(53944), sin_addr=inet_addr("118.166.75.229")}, [112->16], SOCK_NONBLOCK) = 9 recvfrom(9, "GET / HTTP/1.1\r\nHost: localhost:"..., 1024, 0, NULL, NULL) = 40 stat("custom_env/html/index.html", {st_mode=S_IFREG|0664, st_size=162, ...}) = 0 openat(AT_FDCWD, "custom_env/html/index.html", O_RDONLY|O_NONBLOCK) = 10 fstat(10, {st_mode=S_IFREG|0664, st_size=162, ...}) = 0 writev(9, [{iov_base="HTTP/1.1 200 OK\r\nServer: nginx/1"..., iov_len=237}], 1) = 237 sendfile(9, 10, [0] => [162], 162) = 162 close(10) = 0 epoll_ctl(7, EPOLL_CTL_ADD, 9, {EPOLLIN|EPOLLRDHUP|EPOLLET, {u32=1479659969, u64=140236456841665}}) = 0 setsockopt(9, SOL_TCP, TCP_NODELAY, [1], 4) = 0 epoll_wait(7, [{EPOLLIN|EPOLLRDHUP, {u32=1479659969, u64=140236456841665}}], 512, 65000) = 1 recvfrom(9, "", 1024, 0, NULL, NULL) = 0 close(9) epoll_wait(7, ``` 其中最後一個系統呼叫 `epoll_wait` 的狀態為正在 blocking 等待 event。 ## 筆記 - [Intel Pin](https://software.intel.com/content/www/us/en/develop/articles/pin-a-dynamic-binary-instrumentation-tool.html) 使用[自己的 CRT ](https://software.intel.com/sites/landingpage/pintool/docs/97503/PinCRT/html/index.html) (C runtime),因此有些 glibc 的函式無法使用 (例如: `clock_gettime`,需以 `syscall()` 直接呼叫。倘若粒度要求不高的話,可以使用 Pin CRT 提供的 [OS_Time()](https://software.intel.com/sites/landingpage/pintool/docs/97503/PinCRT/html/group__OS__APIS__TIME.html#gacec6776bbde1899ac0c0d56745b0a0d5))。