Как найти все дочерние процессы?
В проекте на основе Linux, над которым я работаю, мне нужно найти все свои дочерние процессы. Невозможно записывать каждый раз, когда кто-то запускается - их нужно найти по факту. Это должен быть чистый C, и я хотел бы сделать это без чтения /proc. Кто-нибудь знает как это сделать?
7 ответов
Я нахожу ваш комментарий о том, что нецелесообразно записывать создание процессов как-то странно, но если вы действительно не можете (возможно, потому что вы не знаете, сколько будет создано, и не хотите сохранять realloc
памяти), тогда я бы открыл все файлы, соответствующие глобусу. /proc/[1-9]*/status
и искать строку, которая говорит PPid: <num>
где <num>
был мой идентификатор процесса.
Обычно вполне возможно записывать дочерние процессы при каждом запуске. для удобства родительскому процессу передается значение pid дочернего процесса в качестве возвращаемого значения вызова fork, который его создает.
Как написано на странице руководства:
pid_t fork(void);
Было бы полезно, если бы вы могли сказать нам, почему вы думаете, что это невозможно.
Вы могли бы использовать попен
Что-то вроде. (Надеюсь, синтаксис достаточно близок)
#include#include #include int main (int argc, char * argv []) { FILE * fp = popen ("ps -C * НАЗВАНИЕ ВАШЕЙ ПРОГРАММЫ ЗДЕСЬ * - формат"%P %p "", "r"); if (fp == NULL) { Е ("ОШИБКА!\ п"); } char parentID [256]; char processID [256]; while (fscanf (fp, "% s% s", parentID, processID)! = EOF) { printf ("PID:% s Parent:% s \ n", processID, parentID); // Проверяем parentID, чтобы увидеть, что это из вашего процесса } pclose (FP); возврат 1; }
Вы можете попробовать это
#include<string.h>
#include <sys/types.h>
#include <unistd.h>
char str[50] = "ps -o pid --ppid ";
char ppid [7];
sprintf(ppid,"%d",getpid());
strcat(str,ppid);
system(str);
ПРИМЕЧАНИЕ. Этот фрагмент кода должен находиться в родительском процессе.
В принципе ps -o pid --ppid <parent_id>
дает pid всех дочерних процессов, чей родитель имеет PID . Теперь мы можем получить PID родительского процесса с помощью getpid(), который возвращает pid_t
и неявно преобразуется в целое число.sprintf преобразует его в строку, и мы объединяем результат с str
чтобы получить полную команду, которая выполняется system()
Если вы пытаетесь получить все дочерние процессы с очень конкретной целью ожидания их завершения, вы можете использовать waitpid(-1, ...):
while (true) {
// Wait for any child exiting
int child_status;
const int child_pid = waitpid(-1, &child_status, 0);
// check child_status
}
Вы можете проанализировать список процессов (ps -ax?), Который включает идентификатор родительского процесса. Вероятно, это можно сделать с помощью простого сценария оболочки.
Если вы хотите отследить события форка и извлечь дочерние pids для целей отладки, есть несколько способов сделать это, включая:
- Использование GDB
- используя strace
- Использование systemtap
- Использование соединителей событий ядра (не уверен, что именно это)
Код в этом репозитории необходимо будет отрегулировать, чтобы он был написан на простом C для удовлетворения вашего запроса, и если вы согласны с этим, если вы удалите все неиспользуемые функции из моего репозитория в своем проекте, это не должно быть так сложно перевести на простой C.
Но это более полезно для людей, которые хотят поддерживать несколько платформ и / или предпочитают C++.
См. Функцию pids_from_ppid(ppid)https://github.com/time-killer-games/enigma-dev/blob/548dc16e96a2a32f8ad9045a4ee18b0206516e62/ENIGMAsystem/SHELL/Universal_System/Extensions/ProcInfo/procinfo.h
Возвращает строку с идентификаторами каждого дочернего процесса, разделенными вертикальной чертой "|" символ в качестве разделителя.
Пользователям Ubuntu и debian необходимо установить libprocps-dev из-за отсутствия заголовков.
sudo apt-get install libprocps-dev libx11-dev
Зависимость libx11-dev является необязательной, потому что весь код X11 в источнике можно опустить, и на вопрос здесь все равно будет дан ответ, поэтому, если вам нужен путь и поддержка X11, вам следует удалить код, связанный с X11, поскольку он в любом случае не имеет отношения к этому вопросу.
Для тех, кто действительно любит / нуждается в X11 и / или C++, это будет работать из коробки в Windows, Mac, Linux и FreeBSD. Поддержка других BSD не так легко осуществима из-за зависимости от libutil. Но он просто использует sysctl() внутри, поэтому теоретически вы должны иметь возможность скомпилировать исходный код для libutil на других BSD, доступных из репозитория FreeBSD github, а затем связать его после того, как вы его построили.