Перейти к содержанию

про system


Гость

Рекомендуемые сообщения

дело вот в чем:

в моей программе 2 параллельных процесса:

в дочернем выполняется командный файл , запущенный с помощью system, родительский в это время ждет окончания дочернего. Так вот, при возникновении некоторого события (сигнала) родительский процесс должен убить дочерний процесс и процесс, в котором выполняется командный файл. Вся сложность в том, как убить последний.

Ссылка на комментарий
Поделиться на другие сайты

я знаю, что fork возвращает идентификатор процесса и знаю как он работает, просто в данном случае fork не подходит. Я думаю сделать так: в командном файле установить переменную окружения, равную результату pidof, а в самой программе воспользоваться getenv.

Ссылка на комментарий
Поделиться на другие сайты

Вообще system использовать не рекомендуется -- поскольку им

ну ооочень легко создаются дырки в безопастности.

Так что fork+exec+wait...

Ссылка на комментарий
Поделиться на другие сайты

Потому что system передает свой аргумент дочернему shellу,

который и выполняет ее со всеми подстановками итд. Поэтому

если не принимать определенных мер безопастности, любой

вызов system может в принципе выполнить что угодно. Например:

char buf[bUFSIZE];

sprintf(buf, "ls -l %s", filename);

system(buf);

Если filename = "; rm -rf .*"

то результат будет плачевным.

А если упомянутые меры предпринимать (escaping там и т. п.),

то использование system уже не дает никаких премуществ перед

fork/exec.

Единственная ситуация, когда использование system оправдано --

выполнение shell-команд по явному запросу пользователя.

Ссылка на комментарий
Поделиться на другие сайты

вся проблема в том, что после exec* все поступившие сигналы будут обрабатываться по умолчанию (если, правда, в загруженной exec*'ом программе не указано иначе). А system позволяет по-прежнему обрабатывать сигналы. Еще мне нужно при поступлении определенного сигнала убить процесс, порожденный system, но я не могу этого сделать так просто, как с fork/exec, потому что system никак не говорит об pid нового процесса. Выходит, либо сигналы, либо pid, а мне нужно и то и другое.

Ссылка на комментарий
Поделиться на другие сайты

newbie писал(а):

>

> вся проблема в том, что после exec* все поступившие сигналы

> будут обрабатываться по умолчанию (если, правда, в

> загруженной exec*'ом программе не указано иначе).

Не совсем так, после exec* сигналы, которым была определена функция обработчик, будут действительно обрабатываться по умолчанию, но сигналы, которые в родительском процессе игнорировались, будут так же игнорироваться и в дочернем процессе.

> Еще мне нужно при

> поступлении определенного сигнала убить процесс,

Все сигналы (включая SIGUSR1 и SIGUSR2), кроме SIGCHLD и SIGCONT, по умолчанию убивают процесс.

> А system

> позволяет по-прежнему обрабатывать сигналы.

system Это не системный вызов ОС, а библиотечная функция! Использования system приводит к обращению к системным вызовам fork и exec. Так что все сигналы, для которых была определена функция обработчик, будут обрабатываться по умолчанию. Это сделано потому, что exec (и соответственно system) замещает программный код процесса, и соответственно никто не гарантирует, что в новом процессе по адресу который записан в диспозиции сигналов, будет вообще какая либо функция!

Кроме того после вызова функции system в новом процессе будут игнорироваться SIGINT и SIGQUIT !!!

Единственный способ создать новый процесс и полностью сохранить диспозицию сигналов использовать только системный вызов fork (без exec!).

Ссылка на комментарий
Поделиться на другие сайты

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

Ссылка на комментарий
Поделиться на другие сайты

Можно послать сигнал сразу группе процессов, и одним выстрелом убить двух зайцев.

СИНТАКСИС

#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, то сигнал не посылается, но выполняется

проверка на возникновение ошибок в процессе.

Ссылка на комментарий
Поделиться на другие сайты

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);

}

Ссылка на комментарий
Поделиться на другие сайты

это, на сколько я понял, аналог 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 дочерним процессом будут игнорированы. Так?

Ссылка на комментарий
Поделиться на другие сайты

SIGINT поступает всем процессам, находящимся в текущей основной группе терминала. Чтобы сын не получал SIGINT нужно

его перевести в собственную группу процессов.

Делается это так:

if ((pid = fork()) < 0) { Error }

else if (!pid) {

// child

setpgid(0, 0);

...

} else {

setpgid(pid, pid);

...

}

Обратите внимание, что setpgid должен быть и в отце,

и в сыне.

Ссылка на комментарий
Поделиться на другие сайты

Да, в данном случае SIGINT будет игнорироваться и в родительском и в дочернем процессе.

Но насколько я понимаю, пришедший сигнал SIGUSR1 выведет родительский процесс из wait, еще до смерти дочернего процесса. Это приведет к появлению зомби.

Ссылка на комментарий
Поделиться на другие сайты

с игнорированием теперь разобрался Smile

>пришедший сигнал SIGUSR1 выведет родительский процесс из wait, >еще до смерти дочернего процесса

вы хотите сказать, что после выполнения обработки SIGUSR1 управление не передастся обратно в wait, и wait не завершится корректно?

Ссылка на комментарий
Поделиться на другие сайты

Я ошибся Sad, все будет работать правильно.

Просто в маннах написано:

Функция 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");

}

Ссылка на комментарий
Поделиться на другие сайты

родительский процесс запускает wait, потом получает SIGUSR1, сын на время становится зомби, затем управление возвращается в wait и родитель узнает о смерти сына. Это понятно. Про терминалы, чесно говоря, не понял: зачем нужно процессы переводить в какую-то другую группу... поставлю вначале программы signal(SIGINT,SIG_IGN) - так будет проще.

Ссылка на комментарий
Поделиться на другие сайты

Поясняю. Запущенному процессу никто не мешает установить свою обработку SIGINT. Тогда при нажатии Ctrl-C он получит и обработает SIGINT.

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
×
×
  • Создать...