Игнорирование сигнала - пример - перенаправление вывода.



 

Эта полезная программа позволяет вам оставлять исполняющуюся в фоновом режиме (background) программу после того, как вы выйдете из системы. Это достигается путем игнорирования сигнала SIGHUP, и исполнения после этого новой программы, командная строка которой переда`тся как аргументы. Этот пример является упрощенной версией команды nohup(1).

В командных процессорах с управлением заданиями, фоновые задания не получают SIGHUP (его получают только процессы первого плана, см. раздел «Терминальный ввод-вывод»), поэтому в таких командных процессорах эта команда не нужна. Для проверки того, что в командном процессоре без управления заданиями ваша программа работает как заявлено, вы можете заменить командный процессор на sh командой exec sh или запустить терминальный эмулятор, указав, что запускать в терминальной сессии, например, командой gnome-term -x /bin/sh -i. Чтобы убедиться, что ваша программа продолжает исполняться после закрытия сессии, можно вывести полный список ваших процессов командой ps -u $USER. Обычно, графическая сессия содержит много процессов; для поиска вашего процесса можно воспользоваться утилитой grep, например ps -u $USER | grep command-name.

15-20   Закрывается дескриптор файла 1. Затем, открывается выходной файл для перенаправления стандартного вывода. open возвращает дескриптор файла 1. Это не является рекомендованным способом переназначать ввод-вывод, но такой код короче.

22   Реакция на сигнал SIGHUP установлена так, чтобы игнорировать этот сигнал.

23   Запускается новая программа с именем argv[1]. Заметьте, что реакции на сигналы SIG_IGN и SIG_DFL не изменяются системным вызовом exec(2). Однако, если бы реакция была установлена на какую-либо функцию обработки, то она была бы сброшена ядром к SIG_DFL, потому что значение указателя на функцию становится неправильным в новой программе.

 

Файл: hangup.c


               ИГНОРИРОВАНИЕ СИГНАЛА - ПРИМЕР

                    ПЕРЕНАПРАВЛЕНИЕ ВЫВОДА

 

1 #include <sys/types.h>

2 #include <fcntl.h>

3 #include <sys/stat.h>

4 #include <signal.h>

5 #define FILE "Hangup.out"

6

7 main(int argc, char *argv[])

8 {

9 int fd;

10

11 if (argc < 2) {

12   printf("usage: %s command [args]\n",argv

13   exit(1);

14  }

15 close(1); /* redirect standard output */

16 if ((fd = open(FILE, O_WRONLY | O_CREAT |

17                  O_APPEND, 0644)) == -1) {

18   perror(FILE);

19   exit(2);

20 }

21

22 signal(SIGHUP, SIG_IGN);

23 execvp(argv[1], &argv[1]);

24 perror(argv[1]);

25 exit(127);

26 }

 

Генерация сигналов

Сигналы могут генерироваться различными способами. Для того, чтобы программно послать сигнал, вы можете использовать команду kill(1) или системные вызовы kill(2) или sigsend(2). Вы можете посылать сигналы только тем процессам, которые имеют ваш идентификатор пользователя. Однако, суперпользователь (root) и/или обладатель привилегии PRIV_PROC_OWNER может послать сигнал любому процессу. Также, можно посылать сигнал SIGCONT любому процессу своей терминальной сессии.

Кроме того, вы можете установить будильник (alarm clock), используя системный вызов alarm(2). После того, как интервал времени в секундах, заданный в качестве аргумента alarm, закончится, ядро пошлёт сигнал процессу, вызвавшему alarm(2).

Кроме того, сигналы генерируются при ошибках, таких, как плохой указатель или ошибка деления с плавающей точкой на ноль. При нажатии некоторых клавиш на клавиатуре терминала, также генерируются сигналы. Например, нажатие клавиши Ctrl-C распознаётся кодом драйвера терминального устройства в ядре и превращается в сигнал SIGINT.

 

Посылка сигнала

 

Вы можете послать сигнал одному или нескольким процессам, используя системный вызов kill(2). Аргументы:

sig - сигнал, который нужно послать. Если sig равен нулю, сигнал не посылается, но выполняется проверка ошибок. Это можно использовать для проверки допустимости значения pid.

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

pid получающий процесс (процессы)
> 0 идентификатор процесса
0 все процессы группы, к которой принадлежит данный процесс
-1 все процессы, чей действительный ID равен эффективному ID посылающего процесса
< -1 все процессы в группе процессов -pid

Из Справочного руководства программиста по kill(2):

sigsend(2) является более гибким способом посылки сигналов процессам. Пользователю рекомендуется использовать sigsend(2) вместо kill(2). sigsend(2) рассматривается далее в этом разделе.

 

Аналогичным образом интерпретирует свой параметр одноимённая команда kill(1). Так, передав -1 в качестве номера процесса, вы можете послать сигнал всем вашим процессам. Например, это может быть полезно, чтобы убить форк-бомбу. Если вы случайно запустили процесс, который вызывает fork(2) в бесконечном цикле, потомки такого процесса быстро переполнят вашу квоту процессов и вы не сможете запустить ни одной команды, даже ps(1), чтобы определить номер родительского процесса или группы процессов форк-бомбы. Для убийства такого дерева процессов можно зайти в систему по ssh(1) от имени другого пользователя, сделать su your-username (при смене uid при помощи setuid(2), не проверяется переполнение квоты процессов) и из полученной командной оболочки убить все ваши процессы командой kill -SIGKILL -1. Если написать просто kill -1, команда kill(1) воспримет параметр, начинающийся с -, как номер сигнала (в данном случае это будет SIGHUP), поэтому обязательно нужно указать номер сигнала.

 

Посылка сигнала

 

sigsend(2) предоставляет более гибкий способ посылки сигнала, чем системный вызов kill(2). Аргументы:

sig - сигнал, который нужно послать. Если sig равен нулю, сигнал не посылается, но выполняется проверка ошибок.

idtype определяет, как будет интерпретироваться id

id определяет процесс(ы), которые должны получить сигнал.

Следующая таблица представляет собой список возможных значений idtype и соответствующий смысл аргумента id.

idtype Получающий процесс (процессы)
P_PID процесс, чей PID равен id
P_PGID все процессы, чей ID группы процессов равен id
P_SID все процессы, чей ID сессии равен id
P_UID все процессы, чей EUID равен id
P_GID все процессы, чей EGID равен id
P_CID все процессы, чей ID класса планировщика равен id [см. priocntl(2)]
P_ALL все процессы; id игнорируется
P_MYID вызывающий процесс; id игнорируется

 


Дата добавления: 2018-06-27; просмотров: 235; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!