最近在 linux
下需要实现2个函数
- 通过
pid
找服务名称
- 根据
服务名称
找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 <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;
}