C: Exec/fork> Неисправные процессы
Я хочу создать много дочерних процессов, используя процедуру fork > exec. Многие процессы заканчиваются очень быстро (менее чем за две минуты, некоторые даже раньше).
Моя первая проблема заключается в том, что я запускаю процесс появления в фоновом режиме с помощью
./spawnbot > logging.txt
[CTRL+Z]
bg 1
disown
Пока все хорошо. Теперь я больше не вижу ни одного из сообщений spawnbot, и они идут прямо в файл logging.txt. Тем не менее, всякий раз, когда создается новый ребенок, я снова вижу всю информацию об этом ребенке в моей консоли. Теперь я хотел, чтобы каждый ребенок имел свой собственный канал - есть ли лучший способ, чтобы дети не отправляли свои выходные сообщения по всему консоль? Должен ли я просто перенаправить его на /dev/null или это делается с некоторым флагом в C?
Во-вторых, все дети действительно не убиты. У меня много процессов в моем ps -ef. Что я могу сделать по этому поводу? Как сделать d
Ответы
Ответ 1
Сначала ваш второй вопрос!
Ваши дети остаются в режиме "зомби", потому что ядро думает, что вы все равно можете получить возвращаемое значение из них.
Если у вас нет намерения получать возвращаемые значения из ваших дочерних процессов, вы должны установить обработчик сигнала SIGCHLD в родительском процессе на SIG_IGN, чтобы ядро автоматически пожинало ваших детей.
signal(SIGCHLD, SIG_IGN);
Первый вопрос зависит от его реализации.
Но вообще говоря, сразу после fork() вы должны использовать close()
, чтобы закрыть старые файловые дескрипторы для 0 и 1, а затем использовать dup2()
, чтобы установить их в нужные значения. Нет времени для примера справа теперь, но надеюсь, что это подтолкнет вас в правильном направлении.
Ответ 2
Ваши дочерние процессы убиваются. Неисправные процессы также называются зомби-процессами; зомби мертвы! Процесс зомби - это не что иное, как запись в таблице процессов, у него нет кода или памяти.
Когда процесс умирает (вызывая _exit
или убитый сигналом), он должен быть извлечен его родителем. Каждый ресурс, используемый процессом, отличным от записи в таблице процессов, исчезает. Родитель должен вызвать wait
или waitpid
. Как только родитель был уведомлен о смерти детского процесса и имел возможность прочитать статус выхода ребенка, дочерняя запись в таблице процессов также исчезает: зомби получают.
Если вы никогда не хотите получать уведомления о смерти ваших детей, игнорируйте сигнал SIGCHLD
; это говорит ядру, что вам не интересно знать судьбу своих детей, и зомби будут получаться автоматически.
signal(SIGCHLD, SIG_IGN)
Если вы хотите только уведомить о смерти своих детей в определенных обстоятельствах, позвоните sigaction
с флагом SA_NOCLDWAIT
. Когда ребенок умирает, если родитель выполняет одно из семейств функций wait
, он будет уведомлен о смерти ребенка и должен быть уведомлен о статусе выхода; в противном случае статус выхода ребенка будет отброшен.
struct sigaction sa;
sa.sa_handler = &my_sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_NOCLDWAIT;
sigaction(SIGCHLD, &sa, NULL);
Что касается вывода, ваши дети пишут те же места, что и родительский, если вы явно не перенаправили их (с помощью close
и open
, или dup
), или несколькими другими возможностями. Вероятно, ваши дети печатают диагностические сообщения на стандартную ошибку (в конце концов, что это такое).
./spawnbot >logging.txt 2>&1
Кроме того, поскольку вы, похоже, хотите отсоединить детей от терминала, вы, вероятно, захотите убедиться, что они не получают SIGHUP, если вы убить терминал. Поэтому используйте nohup
:
nohup ./spawnbot >logging.txt 2>&1 &
disown