日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

killall为什么有时候会找不到进程?

發布時間:2024/3/13 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 killall为什么有时候会找不到进程? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

前言

在Linux下有很多命令用于殺死進程,它們可以用于不同的場景,例如通過進程名殺死進程,通過pid殺死進程。這些方法我不準備一一列舉,本文想說明的一個問題是,為什么明明通過ps找到了進程,但是通過killall卻說找不到呢?如果你沒有遇到過這樣的問題?那你更要注意了!

killall簡介

與kill不同的是,killall可以根據進程名來殺死進程,不像kill,可能先需要使用ps(可以參考《ps命令實例詳解》)找到進程id,然后發送信號,就像下面這樣:

$?ps?-ef|grep?hello root??????15530??6335??0?14:55?pts/4????00:00:00?./hello $?kill?-9?15530

這樣進程就被我們殺死了,我們可以直接使用killall:

$?killall?hello

是不是覺得方便多了?

而且由于killall是根據名稱殺死進程,因此如果當前運行著大量的hello程序,那么可以一次性殺死所有hello程序。

除此之外,它還有很多參數,例如忽略大小寫,根據模式匹配進程名,殺死某個時間的進程等等,這里就不詳解介紹了,有興趣的可以查看man killall手冊。

今天這里想要說明的是一種killall失效的情況。

killall失效了?

我寫了一個自己的hello程序,然后嘗試使用killall殺死正在運行的hello程序。

$??killall?hello hello:?no?process?found

什么?竟然說找不到?一個ps丟過來:

$?ps?-ef|grep?hello root??????15765??6335??0?15:05?pts/4????00:00:00?./hello

所以killall你到底行不行?

為何

為了找出killall失效的原因,我們必須知道它到底是如何通過進程名找到進程的。
這個時候就需要祭出我們的神器strace了,看看killall殺死一個普通進程到底做了哪些事情:

$?strace?killall?hello open("/proc/100/cmdline",?O_RDONLY)?????=?3 fstat(3,?{st_mode=S_IFREG|0444,?st_size=0,?...})?=?0 read(3,?"",?1024)???????????????????????=?0 close(3)????????????????????????????????=?0 open("/proc/104/stat",?O_RDONLY)????????=?3 fstat(3,?{st_mode=S_IFREG|0444,?st_size=0,?...})?=?0 read(3,?"104?(ipv6_addrconf)?I?2?0?0?0?-1"...,?1024)?=?161 close(3)????????????????????????????????=?0 open("/proc/113/stat",?O_RDONLY)????????=?3 fstat(3,?{st_mode=S_IFREG|0444,?st_size=0,?...})?=?0 read(3,?"113?(kstrp)?I?2?0?0?0?-1?6923888"...,?1024)?=?153 close(3)????????????????????????????????=?0 open("/proc/137/stat",?O_RDONLY)????????=?3 fstat(3,?{st_mode=S_IFREG|0444,?st_size=0,?...})?=?0 read(3,?"137?(charger_manager)?I?2?0?0?0?"...,?1024)?=?163 close(3)????????????????????????????????=?0 open("/proc/137/cmdline",?O_RDONLY)?????=?3 fstat(3,?{st_mode=S_IFREG|0444,?st_size=0,?...})?=?0 read(3,?"",?1024)???????????????????????=?0

打印結果很多,我只提取了部分,可以看到的是,killall會去proc文件系統(proc文件系統可以參考《Linux中不可錯過的信息寶庫》)下查找各個進程id下的stat文件和cmdline,stat文件是怎樣的呢?我們隨便找一個看看:

$?cat?/proc/16131/stat? 16131?(hello)?S?6335?16131?6335?34820?16131?1077936128?70?0?0?0?0?0?0?0?20?0?1?0?2465163?4321280?194?18446744073709551615?4194304?4196092?140734969955328?0?0?0?0?0?0?1?0?0?17?0?0?0?0?0?0?6295056?6295608?19099648?140734969962804?140734969962812?140734969962812?140734969966576?0

我們不要被這么多內容嚇到了,可以明顯看到的是,里面有hello啊。至此我們可以猜測,killall命令會去讀取進程在proc文件系統中的stat文件里的名字。那么如果這么名字和你要殺死的進程對不上不就找不到了嗎?

至此,想必你已經明白前面問題的原因了。

如何給自挖坑

那么怎樣修改stat中顯示的名字呢?我們可以使用prcl函數,話不多少,直接看示例代碼:

//來源:公眾號【編程珠璣】 //作者:守望先生 #include<stdio.h> #include<sys/prctl.h> #include<unistd.h> int?main(void) {prctl(PR_SET_NAME,"bianchengzhuji");?sleep(100);//防止進程立即退出,便于觀察return?0; }

這個時候再編譯運行程序查看stat和status中的名字:

$?gcc?-o?hello?hello.c $?cat?/proc/pid/stat??#這里的pid換成示例的進程id 16441?(bianchengzhuji)?S?6335?16441?6335?34820?16441?1077936128?69?0?0?0?0?0?0?0?20?0?1?0?2535513?4321280?156?18446744073709551615?4194304?4196188?140724949606512?0?0?0?0?0?0?1?0?0?17?3?0?0?0?0?0?6295056?6295616?31719424?140724949614900?140724949614908?140724949614908?140724949618672?0 $?more?/proc/pid/status Name:????bianchengzhuji Umask:????0002 State:????S?(sleeping) Tgid:????16441 Ngid:????0 Pid:????16441 PPid:????6335

是不是發現名字變了呢?雖然進程名還是hello,但是killall已經找不到它了,不過:

$?killall?bianchengzhuji

還是可以的。

為什么會出現這種情況呢?
想象一下,你們公司內部不想重復造輪子,搞了一套開發框架,main函數在框架里寫好了,通過庫的形式給你們使用,可能名字早就定好了。或者是多線程程序,它的名字是main。

但是,這里需要特別注意的是,如果名字超過了15個字符,在stat和status文件中看到的將會看到被截斷的名字

玩點刺激的

既然看到這里了,不如再玩點刺激的。

看看下面的代碼:

//來源:公眾號【編程珠璣】 #include<stdio.h> #include<string.h> #include<unistd.h> int?main(int?argc,char?*argv[]) {strncpy(argv[0],"bianchengzhuji",sizeof("bianchengzhuji"));sleep(100);return?0; }

是不是發現和前面例子的main函數不一樣?參考這里(《C語言的main到底該怎么寫》)
這個時候你去編譯運行:

$?gcc?-o?hello?hello.c $?./hello

然后嘗試使用ps去查找進程:

$?ps?-ef|grep?hello root??????17831?17818??0?16:09?pts/26???00:00:00?grep?--color=auto?hello

然后你就會驚喜的發現找不到hello進程。
但是使用:

$?ps?-ef|grep?shouwangxiansheng root??????17938??6335??0?16:12?pts/4????00:00:00?shouwangxiansheng root??????17954?17924??0?16:12?pts/27???00:00:00?grep?--color=auto?shouwangxiansheng hyb@ub

就可以找到。

這種情況下直接改變了程序的命令名,因此ps之類的找不到。
這個時候看命令名是什么呢?

$?cat?/proc/17938/cmdline shouwangxiansheng

不過這個時候killall還是可以找到它!也就是你可以使用killall hello殺死它。

總結

如果你發現你的程序無法通過killall 進程名的方式殺死的話,不妨看看proc文件系統中這個進程的stat文件或者status文件中的名。

推薦閱讀:

每天都在用printf,你知道變長參數是怎么實現的嗎

幾個命令了解ELF文件的”秘密“

?

首發:公眾號【編程珠璣】

作者:守望先生

ID:shouwangxiansheng

關注公眾號【編程珠璣】,獲取更多Linux/C/C++/算法/計算機基礎/工具等原創技術文章。后臺免費獲取經典電子書和視頻資源

總結

以上是生活随笔為你收集整理的killall为什么有时候会找不到进程?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。