从我在网上看到的情况来看,你在c++中调用kill方法来查看进程是否还活着。问题是 PID 被循环,而您寻找的相同 PID 可能不是同一个进程。我有一个程序,其中有两个进程,这两个进程不是彼此的子进程。与他们通信的唯一方式是IPC。我希望当客户端进程关闭时我的主机进程也关闭。为了做到这一点,我必须知道客户端的进程何时不再存在。
在 Windows 中,它们有一个所谓的进程处理程序,它将保留 PID 不被回收,直到创建该句柄的进程被关闭。我想知道如何在 macOS/Linux (POSIX) 系统上实现这一点。
有问题的代码作为 PID 被回收。
if (0 == kill(pid, 0))
{
// Process exists.
}
答案1
从我在网上看到的情况来看,你在c++中调用kill方法来查看进程是否还活着。问题是 PID 被循环,而您寻找的相同 PID 可能不是同一个进程
确实如此,所以这种kill
方法确实不是工作。真的,故事到这里就结束了。它不是一个有效的工具。
两种选择:
- 如果你正在监视的进程是你的子进程(或你自己的进程组中的进程),则
waitpid
专门用于监视它何时退出 - 如果过程是不是对于您的子进程,POSIX“理想”表明您自己的进程没有必要与该进程的生命周期紧密交互(至少这是我从
waitpid
的限制中得出的结论)。您可以希望拥有“跟踪”权限并用于ptrace
附加到其他进程并等待exit
调用。
答案2
解决方案是保留PID在窗户上通过缓存并且不关闭process handle
.对于POSIX
系统,我们只需从内核 OS DEPENDANT!
然后检查缓存的开始时间是否等于当前的开始时间。如果没有检测到 PID 冲突,则返回 false。
视窗:
#include <windows.h>
#include <iostream>
#include <vector>
#include <map>
map<DWORD, HANDLE> handles;
bool isProcessAlive(DWORD pid)
{
HANDLE process;
if(handles.find(pid) == handles.end())
{
process = OpenProcess(SYNCHRONIZE, FALSE, pid);
handles[pid] = process;
}
else
{
process = handles[pid];
}
DWORD ret = WaitForSingleObject(process, 0);
bool isRunning = ret == WAIT_TIMEOUT;
if(!isRunning)//close the cached handle to free the PID and erase from the cache
{
CloseHandle(process);
handles.erase(pid);
}
return isRunning;
}
苹果系统:
#include <signal.h>
#include <stddef.h>
#include <sys/_types/_timeval.h>
#include <sys/errno.h>
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <cstring>
#include <iostream>
#include <map>
#include <string>
/**
* map of unsigned long, creation time either in jiffies, ms, or in clock ticks or different on mac even. so we keep it as a string
*/
std::map<unsigned long, string> handles;
/**
* returns true if the process is alive and attempts to suggest a handle to linux's os that we are reading the directory /proc/[PID] reserve this PID till program shutdown
*/
bool isProcessAlive(unsigned long pid)
{
// Get process info from kernel
struct kinfo_proc info;
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid };
size_t len = sizeof info;
memset(&info,0,len);
int rc = sysctl(mib, (sizeof(mib)/sizeof(int)), &info, &len, NULL, 0);
//exit program sysctl failed to verify PID
if (rc != 0)
{
handles.erase(pid);
return false;
}
//extract start time and confirm PID start time equals org start time
struct timeval tv = info.kp_proc.p_starttime;
if(tv.tv_sec == 0)
{
handles.erase(pid);
return false;
}
string time = to_string(tv.tv_usec) + "-" + to_string(tv.tv_sec);
if(handles.find(pid) != handles.end())
{
string org_time = handles[pid];
if(org_time != time)
{
cout << "PID Conflict PID:" << pid << " org_time:" + org_time << " new_time:" << time << endl;
handles.erase(pid);
return false;
}
}
else
{
handles[pid] = time;
}
return true;
}
Linux:
#include <iostream>
#include <vector>
#include <map>
#include <signal.h>
#include <dirent.h>
#include <errno.h>
#include <fstream>
#include <iostream>
#include <iterator>
#include <sstream>
#include <fstream>
#include <vector>
#include <cstring>
#include <cerrno>
#include <ctime>
#include <cstdio>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <string>
#include "/usr/include/x86_64-linux-gnu/sys/param.h"
/**
* map of unsigned long, creation time either in jiffies, ms, or in clock ticks or different on mac even. so we keep it as a string
*/
std::map<unsigned long, string> handles = {};
/**
* returns true if the process is alive and attempts to suggest a handle to linux's os that we are reading the directory /proc/[PID] reserve this PID till program shutdown
*/
bool isProcessAlive(unsigned long pid)
{
ifstream procFile;
string f = "/proc/"+ std::to_string(pid)+ "/stat";
procFile.open(f.c_str());
if(!procFile.fail())
{
//get creation time of current pid's process
char str[255];
procFile.getline(str, 255); // delim defaults to '\n'
vector<string> tmp;
istringstream iss(str);
copy(istream_iterator<string>(iss),
istream_iterator<string>(),
back_inserter<vector<string> >(tmp));
string creation_time = tmp.at(21);
//check if the process's creation time matches the cached creation time
if(handles.find(pid) != handles.end())
{
string org = handles[pid];
//if the pid's creation time is not the cached creation time we assume it's not the same process and the original has closed
//unlike java the ==,!= actually checks .equals() when comparing
if(creation_time != org)
{
std::cerr << "PID conflict:" + to_string(pid) + " orgCreationTime:" + org + " newCreationTime:" + creation_time;
handles.erase(pid);
procFile.close();
return false;
}
}
handles[pid] = creation_time;
procFile.close();
return true;
}
handles.erase(pid);
procFile.close();
return false;
}