Linux下列表所有進程、根據進程名得到pid和根據pid得到進程名

Linux下的當前正在運行的進程信息均存放在/proc目錄下,有一系列以數字爲名的子目錄,每一個子目錄對應一個進程,子目錄名就是進程的pid。子目錄下的status文件內容就是進程的基本信息,包括進程名、pid、ppid等。因此,若要掃描系統當前正在運行的所有進程,只需要遍歷/proc目錄下所有以數字爲名的子目錄下的status即可。據此,可得到獲取當前系統所有進程快照、根據pid獲得進程名和根據進程名獲得pid的程序,如下所示:

#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define BUF_SIZE 1024
#define MAX_PROCESS_PATH 1024
#define PROC_NAME_FIELD ("name:")
#define PARENT_PID_FIELD ("ppid:")

#ifndef __cplusplus
typedef enum {false, true} bool;
#endif // __cplusplus

typedef struct __tagProcessEntry
{
   pid_t pid;
   pid_t ppid;
   char processName[MAX_PROCESS_PATH];
} ProcessEntry;

void string2lower(const char src[], char dest[])
{
   int length = strlen(src);
   int index;
   for(index = 0; index < length; index ++)
   {
      dest[index] = ((src[index] >= 'A') && (src[index] <= 'Z')) ? src[index] + 0x20 : src[index];
   }
   dest[length] = '\0';
}

int createProcessSnapshot(ProcessEntry pes[], int maxCount)
{
   int processCount = 0;
   DIR *dir;
   struct dirent *dirEntry;
   FILE *fp;
   char filePath[MAX_PROCESS_PATH];
   char fieldName[32];
   char fieldValue[MAX_PROCESS_PATH];
   char buf[BUF_SIZE];

   dir = opendir("/proc");
   if (NULL != dir)
   {
      while((dirEntry = readdir(dir)) != NULL) //循環讀取路徑下的每一個文件/文件夾
      {
         //如果讀取到的是"."或者".."則跳過,讀取到的不是文件夾名字也跳過
         if ((strcmp(dirEntry->d_name, ".") == 0) || (strcmp(dirEntry->d_name, "..") == 0) || (DT_DIR != dirEntry->d_type))
         {
            continue;
         }

         sprintf(filePath, "/proc/%s/status", dirEntry->d_name); //生成要讀取的文件的路徑
         fp = fopen(filePath, "r");
         if (NULL != fp)
         {
            do {
               if (fgets(buf, BUF_SIZE - 1, fp) == NULL)
               {
                  break;
               }
               sscanf(buf, "%s %s", fieldName, fieldValue);
               string2lower(fieldName, fieldName);
               if (strcmp(fieldName, PROC_NAME_FIELD) == 0)
               {
                  strcpy(pes[processCount].processName, fieldValue);
               }
               else if (strcmp(fieldName, PARENT_PID_FIELD) == 0)
               {
                  pes[processCount].ppid = atoi(fieldValue);
               }
            } while(!feof(fp));
            fclose(fp);

            pes[processCount].pid = atoi(dirEntry->d_name);
            processCount ++;
            if (processCount >= maxCount)
            {
               break;
            }
         }
      }
      closedir(dir);
   }
   return processCount;
}

int getPidByName(const char *procName, pid_t pids[], int maxCount)
{
   DIR *dir;
   struct dirent *dirEntry;
   FILE *fp;
   char filePath[MAX_PROCESS_PATH];
   char currProcName[MAX_PROCESS_PATH];
   char buf[BUF_SIZE];
   int pidCount = 0;

   dir = opendir("/proc");
   if (NULL != dir)
   {
      while((dirEntry = readdir(dir)) != NULL) //循環讀取路徑下的每一個文件/文件夾
      {
         //如果讀取到的是"."或者".."則跳過,讀取到的不是文件夾名字也跳過
         if ((strcmp(dirEntry->d_name, ".") == 0) || (strcmp(dirEntry->d_name, "..") == 0) || (DT_DIR != dirEntry->d_type))
         {
            continue;
         }

         sprintf(filePath, "/proc/%s/status", dirEntry->d_name); //生成要讀取的文件的路徑
         fp = fopen(filePath, "r"); //打開進程描述文件
         if (NULL != fp)
         {
            if (fgets(buf, BUF_SIZE - 1, fp) == NULL)
            {
               fclose(fp);
               continue;
            }
            sscanf(buf, "%*s %s", currProcName);

            if (strcmp(procName, currProcName) == 0)
            {
               pids[pidCount] = atoi(dirEntry->d_name);
               pidCount ++;
               if (pidCount >= maxCount)
               {
                  break;
               }
            }
            fclose(fp);
         }
      }
      closedir(dir);
   }
   return pidCount;
}

bool getNameByPid(pid_t pid, char procName[])
{
   char pidPath[BUF_SIZE];
   char buf[BUF_SIZE];
   bool success = false;

   sprintf(pidPath, "/proc/%d/status", pid);
   FILE *fp = fopen(pidPath, "r");
   if (NULL != fp)
   {
      if (fgets(buf, BUF_SIZE - 1, fp) != NULL)
      {
         sscanf(buf, "%*s %s", procName);
         success = true;
      }
      else
      {
         success = false;
      }
      fclose(fp);
   }

   return success;
}

int main(int argc, char **argv)
{
   char procName[MAX_PROCESS_PATH];
   pid_t pids[32];
   ProcessEntry pes[1024];

   pid_t currPid = getpid();
   printf("pid of this process:%d\n", currPid);
   getNameByPid(currPid, procName);
   printf("task name is %s\n", procName);
   strcpy(procName, "eclipse");
   int pidCount= getPidByName(procName, pids, sizeof pids / sizeof pids[0]);
   for(int index = 0; index < pidCount; index ++)
   {
      printf("pid of process %s: %d\n", procName, pids[index]);
   }

   int procCnt = createProcessSnapshot(pes, sizeof pes / sizeof pes[0]);
   printf("%d processes found.\n", procCnt);
   for(int index = 0; index < procCnt; index ++)
   {
      printf("proc: %-16s, pid: %6d, ppid: %6d.\n", pes[index].processName, pes[index].pid, pes[index].ppid);
   }

   return 0;
}

上述代碼大部分源於網上材料,我在這裏只是整理了一下,做爲筆記。

發佈了54 篇原創文章 · 獲贊 10 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章