最近需要實現一個功能,即在一個Linux C程序中,已知其他進程的名字,需要獲得該進程的PID,經過一番上網搜索,找到兩種可行的方法:
1.通過popen創建一個管道,執行shell命令並得到返回結果
2.通過搜索/proc文件夾下的文件內容,得到進程PID(順帶演示一下Linux C中如何讀取一個文件夾中的內容)
爲了方便進行測試,首先隨便寫了一段代碼如下:
#include<stdio.h>
void main()
{
char c;
scanf("%c", &c);
}
將代碼編譯爲二進制文件test,並使用./test運行,由於該代碼中由於有scanf函數存在,會一直阻塞,下面就可以運行其它程序來查詢這個進程的PID了。
一、通過popen的方法
我們知道,在shell下可以通過下述命令來得到進程test的PID:
ps -e | grep 'test' | awk '{print $1}'
(注:這個命令中,名字中含有test字樣的進程都會被掃描到,如果只針對名字恰好爲test的進程,則需要修改這個命令)
那麼在Linux C程序中,只要將這個命令移到shell環境中執行一下,並讀取其執行結果即可。在Linux C程序中執行shell命令可以通過popen函數,該函數會返回一個文件指針,可以像操作文件一樣對這個返回的指針進行操作。關於popen函數的細節,網上一搜一大把,這裏就不說了,直接上代碼:
#include<stdio.h>
#include<string.h>
void main()
{
FILE *fp = popen("ps -e | grep \'test\' | awk \'{print $1}\'", "r");//打開管道,執行shell 命令
char buffer[10] = {0};
while (NULL != fgets(buffer, 10, fp)) //逐行讀取執行結果並打印
{
printf("PID: %s", buffer);
}
pclose(fp); //關閉返回的文件指針,注意不是用fclose噢
}
二、通過搜索/proc文件夾下的內容獲取進程PID
在系統的/proc文件夾下,保存有系統當前所有進程的信息,比如一個進程的PID爲10000,那麼/proc下會有一個名字爲10000的文件夾,其中包含有該進程的幾乎所有信息:其中/proc/10000/cmdline文件中保存了啓動該進程時使用的命令行。
由於剛纔的進程是通過./test運行的,因此只要遍歷/proc下的文件夾,如果發現某個文件夾中的cmdline文件內容爲./test,則該文件夾的名字即爲進程的PID,代碼如下:
#include<dirent.h>
#include<stdio.h>
#include<string.h>
void main()
{
DIR *dir;
struct dirent *ptr;
FILE *fp;
char filepath[50];//大小隨意,能裝下cmdline文件的路徑即可
char filetext[50];//大小隨意,能裝下要識別的命令行文本即可
dir = opendir("/proc"); //打開路徑
if (NULL != dir)
{
while ((ptr = readdir(dir)) != NULL) //循環讀取路徑下的每一個文件/文件夾
{
//如果讀取到的是"."或者".."則跳過,讀取到的不是文件夾名字也跳過
if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) continue;
if (DT_DIR != ptr->d_type) continue;
sprintf(filepath, "/proc/%s/cmdline", ptr->d_name);//生成要讀取的文件的路徑
fp = fopen(filepath, "r");//打開文件
if (NULL != fp)
{
fread(filetext, 1, 50, fp);//讀取文件
filetext[49] = '\0';//給讀出的內容加上字符串結束符
//如果文件內容滿足要求則打印路徑的名字(即進程的PID)
if (filetext == strstr(filetext, "./test")) printf("PID: %s\n", ptr->d_name);
fclose(fp);
}
}
closedir(dir);//關閉路徑
}
}