#c #c #fork
#c #c #форк
Вопрос:
есть ли способ для разветвленного дочернего элемента проверить другого разветвленного дочернего элемента, чтобы, если другому разветвленному дочернему элементу требуется больше времени, чем обычно, для выполнения своих обязанностей, первый дочерний элемент мог выполнять предопределенные шаги? если это так, мы будем признательны за пример кода.
Ответ №1:
ДА. Просто разветвляйте процесс, за которым нужно следить, из процесса, чтобы наблюдать за ним.
if (fork() == 0) {
// we are the watcher
pid_t watchee_pid = fork();
if (watchee_pid != 0) {
// wait and/or handle timeout
int status;
waitpid(watchee_pid, amp;status, WNOHANG);
} else {
// we're being watched. do stuff
}
} else {
// original process
}
Чтобы подчеркнуть: существует 3 процесса. Оригинал, процесс-наблюдатель (который обрабатывает время ожидания и т.д.) И фактический отслеживаемый процесс.
Ответ №2:
Для этого вам нужно будет использовать некоторую форму IPC, и именованные сегменты разделяемой памяти здесь имеют смысл. Ваш первый дочерний элемент может прочитать значение в именованном сегменте, которое другой дочерний элемент установит, как только завершит свою работу. Ваш первый дочерний элемент может установить тайм-аут, и как только этот тайм-аут истечет, проверьте значение — если значение не установлено, тогда сделайте то, что вам нужно сделать.
Код может сильно различаться в зависимости от C или C , вам нужно выбрать, какой именно. Если C , вы можете использовать boost::interprocess
для этого — в котором есть много примеров использования общей памяти. Если C, то вам придется собрать это вместе, используя собственные вызовы для вашей ОС — опять же, это должно быть довольно просто — начните с shmget()
Ответ №3:
Это некоторый ориентировочный код, который мог бы помочь вам решить проблему в среде Linux.
pid_t pid = fork();
if (pid == -1) {
printf("fork: %s", strerror(errno));
exit(1);
} else if (pid > 0) {
/* parent process */
int i = 0;
int secs = 60; /* 60 secs for the process to finish */
while(1) {
/* check if process with pid exists */
if (exist(pid) amp;amp; i > secs) {
/* do something accordingly */
}
sleep(1);
i ;
}
} else {
/* child process */
/* child logic here */
exit(0);
}
… эти 60 секунд не очень строгие. вы могли бы лучше использовать таймер, если хотите более строгого измерения времени. Но если вашей системе не нужна критическая обработка в реальном времени, все должно быть просто отлично, вот так.
exist(pid)
относится к функции, у вас должен быть код, который просматривает, proc/pid
где pid
— идентификатор процесса дочернего процесса.
При желании вы можете реализовать функцию, exist(pid)
используя другие библиотеки, предназначенные для извлечения информации из /proc
каталога, такие как procps
Комментарии:
1. Где один дочерний элемент проверяет другого? похоже, что родитель что-то делает.
2. Да, я заканчивал ответ. Посмотрите на новую редакцию, где говорится
exist(pid)
3. Чтобы проверить существование процесса, используйте kill(pid, 0). Сигнал 0 ничего не сделает, но системный вызов kill вернет успех или неудачу.
4. Проверка на существование таким способом имеет условия гонки, если только вы не знаете (1), что родительский элемент еще не ожидал этого pid, и (2) сам родительский элемент каким-либо образом не завершился.
Ответ №4:
Единственные процессы, которые вы можете wait
использовать, — это ваши собственные прямые дочерние процессы — не братья и сестры, не ваши родители, не внуки и т.д. В зависимости от потребностей вашей программы, решение Мэтта может вам подойти. Если нет, то вот несколько других альтернатив:
-
Забудьте об ожидании и используйте другую форму IPC. Для надежности это должно быть что-то, где неожиданное завершение процесса, которого вы ожидаете, приводит к получению события. Лучшее, что я могу придумать, это открыть
pipe
, который совместно используют оба процесса, и передать конец канала записи процессу, которого вы хотите дождаться (убедитесь, что другие процессы не оставляют конец записи открытым!). Когда процесс, удерживающий конец записи, завершится, он будет закрыт, и тогда будет указан конец чтенияEOF
(read
будет блокировать его до тех пор, пока конец записи не будет закрыт, затем вернет чтение нулевой длины). -
Забудьте об IPC и используйте потоки. Одним из преимуществ потоков является то, что сохраняется атомарность «процесса». Отдельные потоки невозможно уничтожить или иным образом завершить вне контроля вашей программы, поэтому вам не нужно беспокоиться об условиях гонки с идентификаторами процессов и распределении общих ресурсов в системно-глобальном пространстве имен (IPC-объекты, имена файлов, сокеты и т.д.). Все примитивы синхронизации существуют исключительно в адресном пространстве вашего процесса.
Комментарии:
1. Одним из приятных аспектов трюка с передачей / записью является то, что он работает, даже если дочерний элемент, за которым нужно следить, является отдельной программой , при условии, что эта программа активно не пытается закрыть ненужные файловые дескрипторы, унаследованные ею от своего родителя.