Bỏ qua điều hướng, tới nội dung chính
Học C
Bài 42.224 phút đọc

strace và chi phí syscall

Sau bài này bạn sẽ làm được

  • Dùng strace để xem và thống kê syscall
  • Phân biệt man mục 2 và mục 3
  • Giải thích vì sao đọc từng byte chậm gấp nghìn lần
  • Dùng ltrace để xem lời gọi thư viện

stracecho bạn xem mọi lời gọi hệ thống một chương trình thực hiện. Nó biến câu "chương trình nói gì với nhân" từ trừu tượng thành một danh sách đọc được, và là công cụ chẩn đoán mạnh nhất trên Linux.

#strace

terminal
# Xem MOI syscall cua mot chuong trinh
strace ./hello
execve("./hello", ["./hello"], 0x7ff...) = 0
brk(NULL)                     = 0x561...
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/.../libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF...", 832)    = 832
mmap(NULL, 8192, PROT_READ|PROT_WRITE, ...) = 0x7f...
...
write(1, "xin chao\n", 9)     = 9
exit_group(0)                 = ?

#Thống kê -c

terminal
# -c: thong ke thay vi liet ke tung dong
strace -c ./perf 1
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 99.82    5.204831           0  20971520           read
  0.10    0.005102          12       417           mmap
  0.05    0.002431           9       260           write
------ ----------- ----------- --------- --------- ----------------
100.00    5.213...             20972197           total
strace -c ./perf 65536
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 42.11    0.000198           0       320           read
 ...
------ ----------- ----------- --------- --------- ----------------

#Lọc và ltrace

strace -e trace=open,openat,read ./prog   # chi cac syscall nay
strace -e trace=file ./prog               # moi syscall lien quan tep
strace -e trace=network ./prog            # moi syscall mang
strace -f ./prog                          # theo doi ca tien trinh CON (fork)
strace -p 1234                            # gan vao tien trinh dang chay
strace -T ./prog                          # in thoi gian moi syscall
strace -o vet.txt ./prog                  # ghi ra tep thay vi man hinh

/* -f RAT huu ich voi chuong trinh dung fork (nhu shell): khong
   co no, strace chi thay tien trinh cha, khong thay con exec gi. */

#Các nhóm syscall

NhómSyscall tiêu biểuChương
Tệpopen, close, read, write, lseek, stat, unlink41
Tiến trìnhfork, execve, exit, wait4, kill, getpid40
Bộ nhớmmap, munmap, brk, mprotect42.3
IPCpipe, socket, bind, listen, accept, connect43, 46
Tín hiệusignal, sigaction, sigprocmask44
Thời gianclock_gettime, nanosleep, gettimeofday42
Ghép kênhselect, poll, epoll_wait46.9

Tự làm thử

  1. Chạy strace trên chương trình Hello World tĩnh và động, so số syscall.
  2. Dùng strace -c chứng minh đọc từng byte gọi nhiều read hơn đọc theo khối.
  3. Dùng strace -e openat tìm mọi tệp một chương trình thử mở.
  4. Gắn strace -p vào một chương trình đang treo và tìm syscall nó đang kẹt.
  5. Dùng strace -f theo dõi một chương trình fork cộng exec.
  6. Dùng ltrace để đếm số lần malloc một chương trình gọi.

Trình chấm điểm tự động sẽ được bổ sung ở giai đoạn sau. Hiện tại bạn tự chạy thử trên máy.

Tóm tắt

  • strace liệt kê mọi syscall một chương trình gọi, kèm tham số và giá trị trả về, hiện cả tên mã lỗi.
  • strace -c thống kê số lần gọi và thời gian, dùng để chứng minh bẫy hiệu năng thay vì đoán.
  • Lọc bằng -e, theo con bằng -f, gắn tiến trình bằng -p; ltrace xem lời gọi thư viện.
  • man 2 là syscall, man 3 là hàm thư viện xây trên syscall.
  • Linux có vài trăm syscall nhưng bạn dùng vài chục; mọi thứ trong C xây trên chúng.