Linux下列表所有进程、根据进程名得到pid和根据pid得到进程名

参考链接:https://blog.csdn.net/kingfox/article/details/104187364

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;
}
文章目录