最近在 linux 下需要实现2个函数

  • 通过 pid服务名称
  • 根据 服务名称pid

根据 pid 查找服务名称

首先需要知道 Linux 所有的信息其实都是以文件形式来呈现
而运行的服务信息保存在 /proc 路径下以 pid 作为文件夹的各种文件中

在这里插入图片描述

其中我们需要的服务名称信息保存在 status 文件里,并且服务名称就在文件的第一行,想办法解析出来即可

status 中的部分内容

所以通过 pid 查找服务名称很简单

  • 尝试读取 /proc/${pid}/status,如果读不到,说明该服务不存在
  • 如果存在尝试读取第一行数据,读不到,也说明不对
  • 最后解析第一行数据里的服务名

解析过程也是需要注意的,以 "Name: systemd" 为例,":" 后面其实是一个制表符,如果我们用 cat /proc/1/status -A,查看一下,得到的结果是:

Name:^Isystemd$
Umask:^I0000$
...

其中 "^I" 代表制表符, "$" 代表换行符,所以切割的思路很多

  • sscanf 函数,类似与正则匹配最简单
  • std::string 通过 find 函数找到 ":" 位置后,利用 substr 函数切割,注意多了一个制表符

所以接下来的代码很好写

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

#define MAX_PATH 260
#define BUF_SIZE 1024

bool findNameByPid(const int &pid, std::string &servername)
{
    char buf[BUF_SIZE];
    char name[MAX_PATH];
    char filepath[MAX_PATH];

    sprintf(filepath, "/proc/%d/status", pid);
    FILE *fp = fopen(filepath, "r");
    if (nullptr == fp)
        return false;

    if (fgets(buf, BUF_SIZE - 1, fp) == nullptr)
    {
        fclose(fp);
        return false;
    }
    fclose(fp);

    sscanf(buf, "%*s%s", name);
    servername = std::string(name);
    return true;
}

根据服务名找服务 pid

使用服务名找 pid 稍微复杂一点
因为需要遍历 proc 文件夹下所有进程下的 status 文件里的服务名,直到得到和给定服务名相同时的 pid

bool findPidByName(const std::string &servername, int &pid)
{
    struct dirent *ptr;
    FILE *fp;
    char buf[BUF_SIZE];
    char filepath[MAX_PATH];
    char cur_task_name[MAX_PATH];

    DIR *dir = opendir("/proc");
    if (nullptr != dir)
    {
        while ((ptr = readdir(dir)) != nullptr)
        {
            if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0))
                continue;

            if (DT_DIR != ptr->d_type)
                continue;

            sprintf(filepath, "/proc/%s/status", ptr->d_name); 
            fp = fopen(filepath, "r");
            if (nullptr != fp)
            {
                if (fgets(buf, BUF_SIZE - 1, fp) == nullptr)
                {
                    fclose(fp);
                    continue;
                }

                sscanf(buf, "%*s%s", cur_task_name);
                if (cur_task_name == servername)
                {
                    pid = atoi(ptr->d_name);
                    fclose(fp);
                    closedir(dir);
                    return true;
                }
                fclose(fp);
            }
        }
        closedir(dir);
    }
    return false;
}
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐