私がオンラインで見たところによると、C ++でkillメソッドを呼び出して、プロセスがまだ生きていることを確認します。問題は、PIDが循環していて、探している同じPIDが同じプロセスではない可能性があることです。お互いの子ではなく、2つのプロセスを持つプログラムがあります。それらと通信できる唯一の方法はIPCです。クライアントプロセスが終了したら、私のホストプロセスも終了したいと思います。これを行うには、クライアントのプロセスがもう存在しない時期を知る必要があります。
Windowsには、ハンドルを作成したプロセスが閉じられるまでPIDがリサイクルされないようにする、いわゆるプロセスハンドラがあります。 macOS / Linux(POSIX)システムでこれを実装する方法を知りたいです。
問題のコードはPIDにリサイクルされます。
if (0 == kill(pid, 0))
{
// Process exists.
}
答え1
私がオンラインで見たところによると、C ++でkillメソッドを呼び出して、プロセスがまだ生きていることを確認します。問題は、PIDがループしていて、探している同じPIDが同じプロセスではない可能性があることです。
はい。したがって、このkill
アプローチはいいえ働く実際、物語はここで終わります。効果的なツールではありません。
2つのオプション:
- 監視しているプロセスが自分の子プロセス(または自分のプロセスグループ内のプロセス)である場合は、
waitpid
特に終了時点を監視してください。 - プロセスが次のような場合いいえ子プロセスに関して、POSIX「理想的」は、自分のプロセスが必ずしもそのプロセスのライフサイクルと密接にやり取りする必要はないと言います(少なくともこれが
waitpid
制限から下された結論です)。 「追跡」権限を持ち、それを使用して他のptrace
プロセスに接続し、exit
呼び出しを待つことができます。
答え2
解決策はPIDを保持窓に通ってください隠れ家システムprocess handle
の場合は、単に起動します。POSIX
コア OS DEPENDANT!
次に、キャッシュされた開始時間が現在の開始時間と同じであることを確認してください。 PID 衝突が検出されない場合は false が返されます。
Windows:
#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;
}