最近在 linux 下需要实现2个函数
- 通过 pid 找 服务名称
- 根据 服务名称 找 pid
首先需要知道 Linux 所有的信息其实都是以文件形式来呈现
而运行的服务信息保存在 /proc 路径下以 pid 作为文件夹的各种文件中
其中我们需要的服务名称信息保存在 status 文件里,并且服务名称就在文件的第一行,想办法解析出来即可
所以通过 pid 查找服务名称很简单
- 尝试读取 /proc/${pid}/status,如果读不到,说明该服务不存在
- 如果存在尝试读取第一行数据,读不到,也说明不对
- 最后解析第一行数据里的服务名
解析过程也是需要注意的,以 "Name: systemd" 为例,":" 后面其实是一个制表符,如果我们用 cat /proc/1/status -A,查看一下,得到的结果是:
Name:^Isystemd$ Umask:^I0000$ ...
其中 "^I" 代表制表符, "$" 代表换行符,所以切割的思路很多
- sscanf 函数,类似与正则匹配最简单
- std::string 通过 find 函数找到 ":" 位置后,利用 substr 函数切割,注意多了一个制表符
所以接下来的代码很好写
#include根据服务名找服务 pid#include #include #include #include #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 稍微复杂一点
因为需要遍历 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;
}



