Запустите процесс в фоновом режиме в Linux с C - PullRequest
8 голосов
/ 04 августа 2010

Я пытаюсь сделать что-то немного странное здесь.Мне нужно запустить процесс, logcat, из демона, который будет работать в фоновом режиме и печатать на терминал без контроля над stdin.Он предназначен для ведения журнала, поэтому в идеале logcat будет печатать сообщения журнала, в то же время позволяя пользователю вводить стандартные команды и инициализировать программы из оболочки.Вот код для демона, который у меня есть.Программа logcat запускается и показывает сообщения журнала, но я не могу вводить какие-либо команды в stdin, так как кажется, что программа взяла под контроль stdin.

int main ( int argc, char** argv, char** env )
{
    int fd;
    if ((fd = open("/dev/console", O_RDWR)) < 0) {
        fd = open("/dev/null", O_RDWR);
    }
    printf("THIS IS A TEST\n");
    dup2(1, fd);
    dup2(2, fd);

    pid_t childpid = fork();

    if(childpid == -1) {
        perror("Failed to fork, logcat not starting");
        return 1;
    }

    if(childpid == 0) {
        //this is the child, exec logcat
        setsid();
        int execReturn = execl("/system/bin/logcat", "logcat", (char *) 0);
    } else {
        //this is the parent do nothing
        close(fd);
        return 0;
    }
    close(fd);
     return 0;
}

Спасибо

Ответы [ 3 ]

4 голосов
/ 04 августа 2010

Команда 'logcat' , по-видимому, предназначена для разработки под Android - это может объяснить странное расположение команды.

Ключевая операция, которую необходимо исправить, - убедиться, что вы закрываетеваш текущий стандартный ввод (терминал) и откройте /dev/null/ для устройства ввода:

close(0);
if ((fd = open("/dev/null", O_RDONLY)) != 0)
    ...error - failed to open /dev/null!

Это означает, что ваш демонизированный дочерний процесс не будет ничего читать с терминала.


Я думаю, что вы хотите сделать следующее:

  1. Запустить вашу программу запуска из командной строки, которая будет иметь стандартный ввод, стандартный вывод и стандартную ошибку, связанную с «терминалом».
  2. Внутри вашей программы вы хотите заменить стандартный ввод так, чтобы он исходил из /dev/null.
  3. Вы хотите оставить стандартный вывод в покое - вы хотите, чтобы logcat записывал в текущий стандартный вывод.
  4. Возможно, вы также хотите оставить стандартную ошибку в покое.

В какой-то момент процедуры вы правильно выполняете демонизация (заимствуя ссылку from @ bstpierre's answer), убедившись, что терминал, к которому вы подключены, не является вашим управляющим терминалом, поэтому прерывания и зависания, отправляемые на терминал, не влияют на вашего демона.Сантехника проще, чем вы настроили - вы должны работать со стандартным вводом и оставить стандартный вывод и стандартную ошибку без изменений (вместо изменения выходов и оставления входа без изменений).

Теперь вы можете захотетьвывод перейти к /dev/console;если это так, то разумно пересмотреть код, чтобы открыть /dev/console.Однако не стоит возвращаться к /dev/null, если вы не можете открыть /dev/console;ваша программа должна сообщить об ошибке и об ошибке (потому что нет смысла записывать logcat в /dev/null!).Убедитесь, что вы открываете консоль с флагом O_NOCTTY, чтобы она не стала управляющим терминалом для демона.

Последний комментарий, который я хотел бы сделать:

  • Вы?Вы уверены, что хотите, чтобы случайный текст появлялся на вашем терминале или консоли, когда он используется для других целей?

Мне не очень нравится, когда это происходит.


См.также: SO 958249

4 голосов
/ 04 августа 2010

Как демонизировать в Linux [неработающая ссылка]

Как демонизировать в Linux [архив описанного выше машинного пути]

gist on github - код взят по ссылке выше

Резюме:

Одна из вещей, с которыми я постоянно сталкиваюсь, - это демоны Linux, которые не работают должным образом. Чтобы правильно выполнить демонизацию, необходимо выполнить следующие шаги.

  • Вызов fork () используется для создания отдельного процесса.
  • Вызов setsid () используется для отделения процесса от родителя (обычно это оболочка).
  • Маска файла должна быть сброшена.
  • Текущий каталог должен быть изменен на что-то доброкачественное.
  • Стандартные файлы (stdin, stdout и stderr) необходимо открыть заново.

Невыполнение любого из этих шагов приведет к процессу демона, который может вести себя неправильно. Типичные симптомы следующие:

  • Запуск демона и выход из него приведут к зависанию терминала. Это особенно неприятно с ssh.
  • Каталог, из которого был запущен демон, остается заблокированным.
  • В оболочке, из которой был запущен демон, появляется ложный вывод.
1 голос
/ 27 апреля 2013

Для этого в glibc есть специальная функция:

#include <unistd.h>

...
/* We are in the parent, yet */
daemon(0,0);
/* Now we are in the child */
...

Подробнее здесь http://linux.die.net/man/3/daemon

...