一、知识点储备
环境:centos6 , x86,g++
需求:输入参数:进程名和超时时间;功能:杀死超时的进程
- 杀死进程的方法:前期考虑用boost::process库以达到跨平台的目的,但是学习之后发现该库是用来管理子进程的,不能用来杀死一个不相干的进程。在linux中杀死一个进程可以使用kill(pid,SIGKILL)函数通过发送信号实现杀死进程的目的。
#include<sys/types.h>
int kill(int pid, int SIG); //第一个参数是进程的id,第二个参数是发送的信号,返回值:0--成功
2.根据进程名获得进程pid
linux系统中所有正在运行的进程都会在/proc/路径下拥有一个以自身pid命名的文件夹,文件夹中存储了该进程相关的一些信息,其中:
exe:是该进程所运行的程序的软连接;
cmd:是该程序所在的目录status文件(/proc/***pid***/status)
:文件中第一行标明了该进程对应的进程名。
所以可以通过遍历/proc/下所有文件夹中的status的方式获取到该进程名对应的所有进程pid
(所谓的进程名就是执行的程序的名字,一个程序可以同时有多个进程去运行,所以一个名字可能对应多个进程pid)
3. 获取进程的运行时长
目前我查到的信息来看,没找到一个封装好的c++函数可以让我们方便得得到一个进程得运行时长,linux中普遍是通过ps命令来获取到进程的开始时间和运行时长。所以在c++中通过代码来启动命令行来得到结果并将获取到的时间变成总秒数
//将此命令中的pname和pid分别替换成自己的进程名和进程pid即可
//得到的就是一个"日-时:分:秒"结构的运行时长
ps -eo pid,etime,cmd | grep [pname] | grep [pid] | awk '{print $2}'
二、以下是各部分的实现代码
1.获取进程pid
//获取进程pid
vector<string> ProcessKiller::getPidFromName(std::string ProcessName){
vector<string> pids;
const char* cprocessName=ProcessName.c_str();
DIR *dir;
struct dirent *ptr;
FILE *fp;
char filepath[50];//存放cmline文件路径
char cur_task_name[50];//存放命令行文本
char buf[BUF_SIZE];
dir = opendir("/proc"); //打开路径,读取下面每一个文件夹
if (NULL != dir)
{
while ((ptr = readdir(dir)) != NULL)
{
//如果是"."或者".."就跳过
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");//打开status文件
if (NULL != fp)
{
if( fgets(buf, BUF_SIZE-1, fp)== NULL ){
fclose(fp);
continue;
}
sscanf(buf,"%*s %s",cur_task_name);
//status中的进程名与要杀死的进程名是否匹配
if(!strcmp(cprocessName,cur_task_name)){
printf("PID: %s\n",ptr->d_name);
pids.push_back(ptr->d_name);
}
fclose(fp);
}
}
vector<string>::iterator it;
std::cout<<cprocessName<<" --pids: ";
for(it=pids.begin();it!=pids.end();it++){
std::cout<<*it<<" ";
}
std::cout<<std::endl;
closedir(dir);
}
return pids;
}
2.获取进程的运行时长(秒数)
这一段代码较长,放到下一篇了
获取进程运行时长
3.杀死进程文章来源:https://www.toymoban.com/news/detail-580071.html
void ProcessKiller::killProcess(vector<string> pids,vector<string> &pids_failed){
vector<string>::iterator it;
for(it=pids.begin();it!=pids.end();it++){
std::cout<<*it<<" ";
int num;
sscanf((*it).c_str(), "%d", &num);
long runtime=get_process_runtime(num, m_processName.c_str()); //get pid's running time;
if(runtime>m_timeout){
if(isRunning(num)==0){
printf("%d is running,start to kill it\n",num);
int retval = kill(num, SIGKILL); //发送SIGKILL信号给进程,要求其停止运行
if (retval<0) //判断是否发生信号
{
printf("kill %d failed",num);
pids_failed.push_back(*it);
}
else
{
printf("%d killed\n", num);
}
}
}else{
printf("œø³Ì[ %d ]runtime<timeout, this is no need to kill it\n ",num);
}
}
}
4.判断进程是否在运行文章来源地址https://www.toymoban.com/news/detail-580071.html
// 0 : running, -1 : exit, -2 : zombie(僵尸进程)
int ProcessKiller::isRunning(int pid)
{
if (0 == kill(pid, 0))
{
std::string path = std::string("/proc/") + std::to_string(pid) + "/status";
std::ifstream fs;
fs.open(path);
if (!fs)
return -1;
std::string line;
while (getline(fs, line))
{
std::size_t found = line.find("State:");
if (found == std::string::npos)
continue;
else
{
found = line.find("zombie");
if (found == std::string::npos)
return 0;
else
return -2; // zombie
}
}
}
else
return -1;
}
到了这里,关于linux c++ 根据进程名杀死一个进程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!