strace命令使用分析

strace命令介紹與用法

1.1 strace概述

在操作系統中,進程分爲用戶態進程和內核態進程,應用程序運行在用戶態,內核態負責對資源包括網絡,磁盤,內存等管理,用戶態進程要訪問這些資源時,需要通過系統調用陷入內核態,由內核來統一管理和分配。
在這裏插入圖片描述
通過系統調用陷入內核態,或者應用程序運行過程中,產生的signal,都可以被strace捕獲到,每個系統調用的名稱,參數,返回值,調用時間通過標準錯誤輸出或者-O選項寫入到文件中,通過分析這些信息,可以在應用程序發生故障時,不用重新編譯程序,就可以捕獲當前進程內部正在做什麼。

1.2 strace用法介紹

下面對strace各個參數的使用方法進行介紹。

1.2.1 strace -p pid

跟蹤正在執行的進程,正在執行的系統調用,先來熟悉幾個查找進程的命令,pidof 查看當前進行運行程序的進程pid,pstree,跟蹤當前進程pid查看,進程樹關係。
在這裏插入圖片描述
由圖可知,server進程的pid爲8146,其中8146創建了線程8147,通過pidof和pstree可以查看進程pid和pstree查看進程樹關係。
現在使用strace -p 8147跟蹤這個進程當前在進行哪些系統調用。
在這裏插入圖片描述
從圖3可知,進程8147進在執行的系統調用是read,write,epoll_wait等,還有這些系統調用的參數,和返回值,從而大概知道進程8147正在執行的情況。

1.2.2 strace -i

現在在原來-p的基礎上,加上-i參數,可以查看系統調用的入口指針。
通過(1.2.1)步驟,重新查看server的pid,並用strace -p pid -i跟蹤系統調用並查看系統調用入口指針。
在這裏插入圖片描述
其中最左側部分就是系統調用入口指針。

1.2.3 strace -t

在原來-p 的基礎上加上-t,跟蹤系統調用,同時查看系統調用的時間戳。結合步(1.2.1)使用strace -p pid -t 跟蹤系統調用,同時查看。
在這裏插入圖片描述
其中最左側的是系統調用的時間戳。
其中strace -t 是精確度是時分秒,-tt是精確爲s。
用法:strace -p pid -tt

在這裏插入圖片描述

1.2.4 strace -T

用於查看系統調用中,每個系統調用花費的時間。
在1.2.1的基礎上,加上-T選項,strace -p pid -T。
在這裏插入圖片描述
如圖7所示,其中最右側部分是每個系統調用花費的時間。

1.2.5 strace -yy

用於查看,進行tcp/udp read/write時,查看socket的五元組詳細信息(比如ip,port,tcp)。
在這裏插入圖片描述

如上圖8所示,加上-yy參數之後,可以看到socket文件描述符5對應的五元組信息爲:
TCP:[172.16.8.188:1883->172.16.8.188:33196]。在一些服務端與客戶端的交互中可以用來分析排查問題。

1.2.6 strace -c

用於統計每個系統調用,時間,調用次數,錯誤次數等。
用法:strace -p pid -c
在這裏插入圖片描述

運行一段時間後,ctrl+c終止

在這裏插入圖片描述

有顏色部分,從左到右,分別是運行時間面分比,運行時間,每次調用花費的時間(單位usecs),調用總次數,調用出錯次數,對應的API。

1.2.7 strace -f

跟蹤系統調用的同時,同時打印pid;如果是父進程,則同時跟蹤打印子進程的系統調用。
查看server程序的父進程pid。
在這裏插入圖片描述
strace -p pid -f
在這裏插入圖片描述

加上-參數之後,其中最左側可以顯示整個應用程序父進程(包括父進程)下的所有子進程的系統調用。

1.2.8 strace -e

前面介紹strace用法,一次性打印所有系統調用,現在加上-e參數之後,可以過濾掉一些系統調用,查看自己想要查看的系統調用,比如只跟蹤網絡,ipc通信或者只跟蹤某個API比如read相關的系統調用。
1. -e trace=desc
跟蹤和文件描述符相關API,比如write/read/select/epoll等
測試用例代碼:
https://github.com/jorinzou/linux_command/tree/master/strace/code_1
code_1是server和client通信的例程,
常試用-e trace=desc,查看看server內部進行的系統調用。
分別編譯和運行server和client。
在這裏插入圖片描述
通過圖,可以查看到5,1,4,相關文件描述符相關的系統調用API。

2. -e trace=file
跟蹤和文件訪問相關的調用(參數中有文件名)。
運行實例:
https://github.com/jorinzou/linux_command/tree/master/strace/trace_file
在後臺用strace跟蹤
在這裏插入圖片描述
3. -e trace=process和進程管理相關的調用,比如fork/exec/exit_group
測試用例:https://github.com/jorinzou/linux_command/tree/master/strace/trace_process
運行進程,並用pstree -p查看進程樹關係,找到父進程,並用strace跟蹤。

4. -e trace=ipc 進程間通信相關,比如shmget等
測試用例:
https://github.com/jorinzou/linux_command/tree/master/strace/trace_ipc
運行此實例代碼,並另外打開一個窗口,進行跟蹤
strace -p pidof b.out -e trace=ipc
在這裏插入圖片描述

5. -e trace=signal 信號發送和處理相關,比如kill/sigaction

運行相關的實現代碼進程,並執行以下命令
strace -p pidof signal -e trace=signal
測試用例:
https://github.com/jorinzou/linux_command/tree/master/strace/trace_process

在這裏插入圖片描述

1.3 案例:結合strace分析線程間死鎖問題

兩個或者多個進程/線程競爭共享資源導致互相等待的現象等待的線程無法獲得資源進而往下執行。
常見死鎖的情形:
線程1獲得鎖A,等待鎖B,線程2獲得鎖B,等待鎖A。

在這裏插入圖片描述
產生死鎖的四個條件

  1. 互斥條件,一個資源只能被一個進程/線程使用
  2. 請求與保護條件,一個進程/線程請求資源而阻塞,對此保持不放
  3. 不剝奪條件,一個進程/線程獲得共享資源,如果沒有使用完,不能被剝奪
  4. 循環等待條件,多個進程/線程形成頭尾先接的等待

避免死鎖的方法

  1. 銀行家算法
  2. 有序資源分配法
  3. 鎖的範圍小
  4. 鎖的臨界區內代碼執行時間短

結合strace分析多線程之間產生死鎖
實例代碼:
https://github.com/jorinzou/linux_command/tree/master/strace/dead_lock

編程運行實例代碼:
在這裏插入圖片描述

使用pstree -p | grep a.out,查看程序的進程樹關係和pid,並用strace跟蹤子線程pid,可以看出10856線程和10857線程被阻塞在同一個鎖0x6010c0,初步定爲這兩個線程競爭同一個鎖導致死鎖。

在這裏插入圖片描述

使用top -p ppid(父進程pid) -H,查看這些死鎖的pid對應的線程是哪些線程,這個需要提前在代碼中設置線程名:如:pthread_setname_np(t2, “Thread2Task”);

在這裏插入圖片描述

從上圖可以看出,線程對應的線程函數,進一步斷定,Thread2Task和Thread3Task發生了死鎖。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章