Гость Опубликовано 10 апреля, 2003 Жалоба Поделиться Опубликовано 10 апреля, 2003 как узнать идентификатор процесса, порождаемого system? Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 10 апреля, 2003 Жалоба Поделиться Опубликовано 10 апреля, 2003 Никак. Да это и не нужно. Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 10 апреля, 2003 Жалоба Поделиться Опубликовано 10 апреля, 2003 дело вот в чем: в моей программе 2 параллельных процесса: в дочернем выполняется командный файл , запущенный с помощью system, родительский в это время ждет окончания дочернего. Так вот, при возникновении некоторого события (сигнала) родительский процесс должен убить дочерний процесс и процесс, в котором выполняется командный файл. Вся сложность в том, как убить последний. Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 10 апреля, 2003 Жалоба Поделиться Опубликовано 10 апреля, 2003 fork() возвращает id порождённого процесса man fork Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 10 апреля, 2003 Жалоба Поделиться Опубликовано 10 апреля, 2003 я знаю, что fork возвращает идентификатор процесса и знаю как он работает, просто в данном случае fork не подходит. Я думаю сделать так: в командном файле установить переменную окружения, равную результату pidof, а в самой программе воспользоваться getenv. Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 11 апреля, 2003 Жалоба Поделиться Опубликовано 11 апреля, 2003 system тривиально пишется через fork/exec. Какие проблемы с fork'ом? Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 11 апреля, 2003 Жалоба Поделиться Опубликовано 11 апреля, 2003 Вообще system использовать не рекомендуется -- поскольку им ну ооочень легко создаются дырки в безопастности. Так что fork+exec+wait... Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 11 апреля, 2003 Жалоба Поделиться Опубликовано 11 апреля, 2003 "поскольку им ну ооочень легко создаются дырки в безопастности." это почему? Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 12 апреля, 2003 Жалоба Поделиться Опубликовано 12 апреля, 2003 Потому что system передает свой аргумент дочернему shellу, который и выполняет ее со всеми подстановками итд. Поэтому если не принимать определенных мер безопастности, любой вызов system может в принципе выполнить что угодно. Например: char buf[bUFSIZE]; sprintf(buf, "ls -l %s", filename); system(buf); Если filename = "; rm -rf .*" то результат будет плачевным. А если упомянутые меры предпринимать (escaping там и т. п.), то использование system уже не дает никаких премуществ перед fork/exec. Единственная ситуация, когда использование system оправдано -- выполнение shell-команд по явному запросу пользователя. Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 13 апреля, 2003 Жалоба Поделиться Опубликовано 13 апреля, 2003 вся проблема в том, что после exec* все поступившие сигналы будут обрабатываться по умолчанию (если, правда, в загруженной exec*'ом программе не указано иначе). А system позволяет по-прежнему обрабатывать сигналы. Еще мне нужно при поступлении определенного сигнала убить процесс, порожденный system, но я не могу этого сделать так просто, как с fork/exec, потому что system никак не говорит об pid нового процесса. Выходит, либо сигналы, либо pid, а мне нужно и то и другое. Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 13 апреля, 2003 Жалоба Поделиться Опубликовано 13 апреля, 2003 newbie писал(а): > > вся проблема в том, что после exec* все поступившие сигналы > будут обрабатываться по умолчанию (если, правда, в > загруженной exec*'ом программе не указано иначе). Не совсем так, после exec* сигналы, которым была определена функция обработчик, будут действительно обрабатываться по умолчанию, но сигналы, которые в родительском процессе игнорировались, будут так же игнорироваться и в дочернем процессе. > Еще мне нужно при > поступлении определенного сигнала убить процесс, Все сигналы (включая SIGUSR1 и SIGUSR2), кроме SIGCHLD и SIGCONT, по умолчанию убивают процесс. > А system > позволяет по-прежнему обрабатывать сигналы. system Это не системный вызов ОС, а библиотечная функция! Использования system приводит к обращению к системным вызовам fork и exec. Так что все сигналы, для которых была определена функция обработчик, будут обрабатываться по умолчанию. Это сделано потому, что exec (и соответственно system) замещает программный код процесса, и соответственно никто не гарантирует, что в новом процессе по адресу который записан в диспозиции сигналов, будет вообще какая либо функция! Кроме того после вызова функции system в новом процессе будут игнорироваться SIGINT и SIGQUIT !!! Единственный способ создать новый процесс и полностью сохранить диспозицию сигналов использовать только системный вызов fork (без exec!). Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 13 апреля, 2003 Жалоба Поделиться Опубликовано 13 апреля, 2003 system не возвращает pid порожденного процесса, потому, что в этом просто нет смысла. Так как процесс, вызвавший system, будет находиться в состояние ожидания смерти дочернего процесса (wait), и продолжит свою работу только после того как дочерний процесс перестанет существовать. Так что возвращать pid погибшего процесса пустая трата времени, вместо этого system при удачном завершении возвращается код выполненной команды. Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 13 апреля, 2003 Жалоба Поделиться Опубликовано 13 апреля, 2003 я кажется что-то начал понимать, пойду опробовать прочитанное. Всем спасибо за ответы. Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 14 апреля, 2003 Жалоба Поделиться Опубликовано 14 апреля, 2003 И то слава Богу! Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 14 апреля, 2003 Жалоба Поделиться Опубликовано 14 апреля, 2003 Можно послать сигнал сразу группе процессов, и одним выстрелом убить двух зайцев. СИНТАКСИС #include #include int kill(pid_t pid, int sig); ОПИСАНИЕ Системный вызов kill используется для того, чтобы послать любой сигнал любому процессу или группе процессов. Если pid больше 0, то сигнал sig посылается процессу pid. Если pid равен 0, то сигнал sig посылается всем процессам текущей группы. Если pid равен -1, то сигнал sig посылается всем процессам, кроме процесса 1 (init). Также смотрите замечания ниже. Если pid меньше -1, то сигнал sig посылается всем процессам группы -pid. Если sig равен 0, то сигнал не посылается, но выполняется проверка на возникновение ошибок в процессе. Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 14 апреля, 2003 Жалоба Поделиться Опубликовано 14 апреля, 2003 int my_system (const char *command) { int pid, status; if (command == 0) return 1; pid = fork(); if (pid == -1) return -1; if (pid == 0) { char *argv[4]; argv[0] = "sh"; argv[1] = "-c"; argv[2] = command; argv[3] = 0; execve("/bin/sh", argv, environ); exit(127); } do { if (waitpid(pid, &status, 0) == -1) { if (errno != EINTR) return -1; } else return status; } while(1); } Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 14 апреля, 2003 Жалоба Поделиться Опубликовано 14 апреля, 2003 это, на сколько я понял, аналог system. Не понятно только одно: зачем нужен цикл do...while, если в любом случае в первой итерации произойдет выход из функции my_system. Ну да ладно, мне то надо выяснить как работать сигналами: ... int pid=0; //глобальная переменная ... int status; signal(SIGINT,SIG_IGN); if((pid=fork())==0) { execl("./my_prog","my_prog",0); } else { signal(SIGUSR1,usr1_handler); wait(&status); } ... void usr1_handler() { kill(pid,SIGKILL); } Я так понял, что этот фрагмент быдет делать следующее: будет создан параллельный процесс, в нем запущена my_prog, родительский процесс будет его ждать, и если поступит сигнал SIGUSR1, дочерний процесс будет убит. При этом (это очень важно) все сигналы SIGINT дочерним процессом будут игнорированы. Так? Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 14 апреля, 2003 Жалоба Поделиться Опубликовано 14 апреля, 2003 SIGINT поступает всем процессам, находящимся в текущей основной группе терминала. Чтобы сын не получал SIGINT нужно его перевести в собственную группу процессов. Делается это так: if ((pid = fork()) < 0) { Error } else if (!pid) { // child setpgid(0, 0); ... } else { setpgid(pid, pid); ... } Обратите внимание, что setpgid должен быть и в отце, и в сыне. Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 14 апреля, 2003 Жалоба Поделиться Опубликовано 14 апреля, 2003 Да, в данном случае SIGINT будет игнорироваться и в родительском и в дочернем процессе. Но насколько я понимаю, пришедший сигнал SIGUSR1 выведет родительский процесс из wait, еще до смерти дочернего процесса. Это приведет к появлению зомби. Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 14 апреля, 2003 Жалоба Поделиться Опубликовано 14 апреля, 2003 В этом случае дочерний процесс потеряет возможность доступа к управляющему терминалу. Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 14 апреля, 2003 Жалоба Поделиться Опубликовано 14 апреля, 2003 с игнорированием теперь разобрался >пришедший сигнал SIGUSR1 выведет родительский процесс из wait, >еще до смерти дочернего процесса вы хотите сказать, что после выполнения обработки SIGUSR1 управление не передастся обратно в wait, и wait не завершится корректно? Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 14 апреля, 2003 Жалоба Поделиться Опубликовано 14 апреля, 2003 Я ошибся , все будет работать правильно. Просто в маннах написано: Функция wait приостанавливает выполнение текущего процесса до тех пор, пока дочерний процесс не завершится, или до появления сигнала, который либо завершает текущий процесс, либо требует вызвать функцию-обработчик. Вот пример программы, которая моделирует подобную ситуацию: #include #include int pid; void trap1(); main(int argc, char *argv[]) { int stat; signal(SIGUSR1, trap1); if(! (pid=fork())) { sleep(1); fprintf(stderr,"===== I am son. My PID=%d\n", getpid()); kill(getppid(),SIGUSR1); fprintf(stderr,"===== Son after kill My PID=%d\n", getpid()); pause(); } fprintf(stderr,"+++++ I am parent. My PID=%d\n",getpid()); fprintf(stderr,"+++++ Parent before wait My PID=%d\n",getpid()); wait(&stat); fprintf(stderr,"+++++ Parent after wait My PID=%d\n",getpid()); system("ps -l"); } void trap1() { kill(pid,SIGKILL); fprintf(stderr,"##### This is signal !!!! My PID=%d\n", getpid()); system("ps -l"); } Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 14 апреля, 2003 Жалоба Поделиться Опубликовано 14 апреля, 2003 Почему? Единственное, чего он не сможет - читать с терминала, что, скорее всего, правильно. Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 15 апреля, 2003 Жалоба Поделиться Опубликовано 15 апреля, 2003 родительский процесс запускает wait, потом получает SIGUSR1, сын на время становится зомби, затем управление возвращается в wait и родитель узнает о смерти сына. Это понятно. Про терминалы, чесно говоря, не понял: зачем нужно процессы переводить в какую-то другую группу... поставлю вначале программы signal(SIGINT,SIG_IGN) - так будет проще. Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 16 апреля, 2003 Жалоба Поделиться Опубликовано 16 апреля, 2003 Поясняю. Запущенному процессу никто не мешает установить свою обработку SIGINT. Тогда при нажатии Ctrl-C он получит и обработает SIGINT. Цитата Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.