@ thatotherguy объясняет ответ в своем комментарии:
"Знаете ли вы, что из-за вашего - 1 вы на самом деле проверяете, что два процесса имеют последовательные pids? Это неудивительное поведение в Linux. Различиямежду дистрибутивами будет зависеть, оптимизирует ли sh дополнительный форк, который он использует для запуска команды "
static inline pid_t XGetActiveProcessId(Display *display) {
unsigned long window = XGetActiveWindow(display);
unsigned char *prop;
Atom actual_type, filter_atom;
int actual_format, status;
unsigned long nitems, bytes_after;
filter_atom = XInternAtom(display, "_NET_WM_PID", True);
status = XGetWindowProperty(display, window, filter_atom, 0, 1000, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop);
unsigned long long_property = prop[0] + (prop[1] << 8) + (prop[2] << 16) + (prop[3] << 24);
XFree(prop);
return (pid_t)(long_property - 1);
}
То - 1 в возвращаемом идентификаторе процесса, который я первоначально добавил, потому что я думал, что когда он возвращалневерный идентификатор процесса, потому что я думал, что когда писал, что fork () должен иметь тот же идентификатор процесса, что и popen, что позже я обнаружил, что это не так. Я вычел один, таким образом делая два разных в противном случае правильных идентификатора процесса, неправильно равных.
Вот правильный способ сделать то, что я намеревался сделать, в моем исходном коде, что привело меня к заданию этого вопроса;Я хотел знать, как определить, происходят ли дочерние процессы fork и popen от общего родительского процесса (при этом удаляя вычитание одного из возвращаемого значения функции GetActiveProcessId ()):
#include <proc/readproc.h>
#include <cstring>
static inline pid_t GetParentPidFromPid(pid_t pid) {
proc_t proc_info; pid_t ppid;
memset(&proc_info, 0, sizeof(proc_info));
PROCTAB *pt_ptr = openproc(PROC_FILLSTATUS | PROC_PID, &pid);
if(readproc(pt_ptr, &proc_info) != 0) {
ppid = proc_info.ppid;
string cmd = proc_info.cmd;
if (cmd == "sh")
ppid = GetParentPidFromPid(ppid);
} else ppid = 0;
closeproc(pt_ptr);
return ppid;
}
Используя вышеизложенноеВспомогательная функция, заменяя цикл while в оригинальном коде этим, позволяет мне делать то, что я делал после:
while (i < 10) {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
if (GetParentPidFromPid(XGetActiveProcessId(display)) == GetParentPidFromPid(getpid()) ||
GetParentPidFromPid(GetParentPidFromPid(XGetActiveProcessId(display))) == GetParentPidFromPid(getppid())) {
window = XGetActiveWindow(display);
break;
}
i++;
}
Как указывало @thatotherguy, некоторые дистрибутивы возвращают другой родительский процесспотому что sh cmd будет использовать run напрямую. Чтобы решить эту проблему, я выполнил или проверил в операторе if, чтобы увидеть, равны ли идентификаторы родительского или «родительского» процесса равным, при попытке пропустить любые родительские процессы со значением sh cmd.
Требуется вспомогательная функцияфлаг компоновщика -lprocps
и пакет libprocps-dev
установлены, если вы работаете в системе на основе Debian. На других дистрибутивах имя пакета будет другим.