引言
上星期新加一好友,在好友的朋友圈動態里看到一張聊天截圖,是署名為“閱碼場”的Linux內核技術交流群, 群友提問:
“請教一個Bash的問題:有沒有什么辦法讓一個新開的進程,一開始就處于暫停狀態,直到我輸入fg?”
巧了,上星期我在嘗試使用ftrace根據進程號(PID)過濾、跟蹤內核執行過程時,迫切需要一個 進程啟動后處于暫停狀態 ,與這位群友一樣,也是滿世界尋找Bash是否有內置類似該功能,為什么我需要它呢?
倘若一個應用程序是死循環,或者執行時間相對較舊,哪怕只執行1秒,我Left Golden Finger完全可以輸入 “Ctrl+Z” 暫停它,借助pidof獲取進程的PID號,將其填入set_ftrace_pid僅過濾該進程信息,輸入 “fg” 恢復進程執行。
再看另一個應用場景,若某個進程執行耗時很短呢?例如“echo”命令轉瞬即逝,完全沒有反應的機會。
再舉例,倘若我就想抓取從應用程序開始執行到“Ctrl+Z”之間幾百毫秒的內核執行過程,我又該怎么?
“拿到源碼重新編譯,在main函數開始時添加足夠的延時。”頭上長尖角的小人說。
“耍流氓!無恥!偷換概念!”頭上另一個長翅膀小人指責。
好吧,別辯論了,回歸正題。
既然群友都和我一樣沒能找到Bash內置實現,再怎么說“閱碼場”聊天群也是人類高質量碼農的聚集地,我相信他也不是伸手黨。那么是時候造車子了,寫幾行代碼實現這個功能,沒騙你,真幾行,發個信號而已。
怎么做
先貼代碼再解釋。
首先要了解系統快捷鍵Ctrl+Z以及命令fg本質是做了什么,Ctrl+Z是向前端應用發送 SIGSTOP信號 ,fg恢復最近一個被暫停的應用發送 SIGCONT信號 ,并放到前臺來執行。
SIGSTOP對應信號19、SIGCONT對應信號18,正如代碼23行和31行所做的那樣。你不相信,那就用API signal()去截獲這兩個信號的處理函數。
既然是信號觸發,那就能用kill命令去替代Ctrl+Z和fg動作:
kill -19
kill -18
命令輸入 “kill -l” 可查閱到所有信號。
寫個測試程序
寫另外一個測試程序child.c,僅打印進程的PID號,以及調試主進程是否能成功傳遞參數給子進程。
文稿貼的兩張圖是測試的方法,主進程傳遞給子進程3個參數“aa bb cc”,剛啟動后子進程被信號暫停(T),左側輸入回車后子進程得以運行(S)。
使用新輪子
恩,輪子造好了,看看它的效果怎么樣,用它協助ftrace抓取echo的執行。
思考
現在左邊窗口輸入./master.elf echo abcdefg,切換到右側窗口輸入腳本ftrace-pid.sh,這個腳本將抓取1秒的數據,再切換到左側窗口按Enter鍵。打開trace文件/tmp/a.txt,怎么樣了,echo命令的執行信息被抓取下來了。
實驗里用到的ftrace-pid.sh腳本我把他的源碼貼在下面。
思考
我在使用kill發送信號時有個疑問,既然應用程序收到SIGSTOP信號后就處于停止狀態,既然停止了,為什么還能處理之后的SIGCONT信號呢?之前是進程可運行,才能被調度、能處理信號,很好理解。之后進程都停止了,又怎么能處理SIGCONT信號恢復執行呢?你能夠用鼠標點擊左下角“開始”菜單關閉計算機,卻無法繼續用鼠標使其開機。所以我猜測信號處理首先是由于調度器處理的。
第二個擴展問題,gdb調試應用程序是可以暫停應用程序執行的,它使用的是ptrace。你能否寫一個應用程序,它利用ptrace原理去暫停子進程執行。我說的暫停位置可不是main,甚至在main之前。應用程序啟動時 “第一個系統調用是什么?” 嘗試找到它,并截獲。
原文標題:僅40行代碼,Linux如何以暫停狀態啟動新進程,當然是發送信號呀
文章出處:【微信公眾號:一口Linux】歡迎添加關注!文章轉載請注明出處。
審核編輯:湯梓紅
-
Linux
+關注
關注
87文章
11322瀏覽量
209857 -
代碼
+關注
關注
30文章
4803瀏覽量
68749 -
應用程序
+關注
關注
37文章
3283瀏覽量
57755
原文標題:僅40行代碼,Linux如何以暫停狀態啟動新進程,當然是發送信號呀
文章出處:【微信號:yikoulinux,微信公眾號:一口Linux】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論