- •Синтаксис
- •Описание
- •Возвращаемые значения
- •Найденные ошибки
- •Соответствие стандартам
- •Описание
- •Возвращаемое значение
- •Соответствие стандартам
- •Синтаксис
- •Описание
- •Возвращаемые значения
- •Найденные ошибки
- •Замечания
- •История linux
- •Соответствие стандартам
- •Наборы сигналов
- •Блокировка сигналов
- •Возвращаемые значения
- •Найденные ошибки
- •Замечания
- •Найденные ошибки
- •Синтаксис
- •Описание
Найденные ошибки
EINVAL
Было задано неверное значение сигнала. Эта ошибка также возникает в случае попытки задания сигналов SIGKILL или SIGSTOP, которые не могут быть "перехвачены".
EFAULT
act, oldact, set, oldset или mask указывают на адрес, не входящий в адресное пространство процесса.
Пример
#include <signal.h>
#include <stdio.h>
sig_atomic_t sig_occured = 0;
sig_atomic_t sig_out = 0;
void sig_handler (int snum)
{
sig_occured = 1;
sig_out++;
}
int main (void)
{
struct sigaction act;
sigemptyset (&act.sa_mask);
act.sa_handler = &sig_handler;
act.sa_flags = 0;
if (sigaction (SIGINT, &act, NULL) == -1) {
fprintf (stderr, "sigaction() error\n");
return 1;
}
while (1) {
if (sig_occured) {
fprintf (stderr, "signal...\n");
sig_occured = 0;
if (sig_out>10) exit(0);
}
}
}
sig_atomic_t - специальный тип данных, математические операции по отношению к переменным данного типа являются атомарными и не могут быть прерваны
Пример 2
//Процесс-сын
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
int main (int argc, char ** argv)
{
int year;
if (argc < 2) {
fprintf (stderr, "child: too few arguments\n");
return 2;
}
year = atoi (argv[1]);
if (year <= 0)
return 2;
if ( ((year%4 == 0) && (year%100 != 0)) ||
(year%400 == 0) )
kill (getppid (), SIGUSR1);
else
kill (getppid (), SIGUSR2);
exit(0);
}
//Процесс-отец
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <wait.h>
#include <signal.h>
/* 0 - no signal, 1 - SIGUSR1, 2 - SIGUSR2 */
sig_atomic_t sig_status = 0;
void handle_usr1 (int s_num)
{
sig_status = 1;
}
void handle_usr2 (int s_num)
{
sig_status = 2;
}
int main (int argc, char ** argv)
{
struct sigaction act_usr1, act_usr2;
sigemptyset (&act_usr1.sa_mask);
sigemptyset (&act_usr2.sa_mask);
act_usr1.sa_flags = 0;
act_usr2.sa_flags = 0;
act_usr1.sa_handler = &handle_usr1;
act_usr2.sa_handler = &handle_usr2;
if (sigaction (SIGUSR1, &act_usr1, NULL) == -1) {
fprintf (stderr, "sigaction (act_usr1) error\n");
exit(1);
}
if (sigaction (SIGUSR2, &act_usr2, NULL) == -1) {
fprintf (stderr, "sigaction (act_usr2) error\n");
exit(1);
}
if (argc < 2) {
fprintf (stderr, "Too few arguments\n");
exit(1);
}
if (!fork()) {
execl ("./child", "child", argv[1], NULL);
fprintf (stderr, "execl() error\n");
exit(1);
}
-while (1) {
if (sig_status == 1) {
printf ("%s: leap year\n", argv[1]);//Високосный
exit(0);
}
if (sig_status == 2) {
printf ("%s: not leap year\n", argv[1]);
exit(0);
}
}
}
alarm - установка времени доставки тревожного сигнала
ОБЗОР
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
ОПИСАНИЕ
Системный вызов alarm выполняет в вызвавший его процесс доставку сигнала " SIGALRM через seconds секунд.
Если seconds равно нулю, то никаких новых тревожных сигналов в очередь поставлено не будет.
Если случиться какое-либо событие (интересно какое? -- прим. пер.), любые предыдущие установки alarm отменяются.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
alarm возвращает количество секунд, оставшихся до момента доставки сигнала, установленного предыдущим вызовом alarm или ноль, если в очереди нет тревожных сигналов.
ЗАМЕЧАНИЯ
Вызовы alarm и setitimer совместно используют один и тот же таймер; они будут конфликтовать друг с другом.
sleep() может быть реализован, используя SIGALRM; так что смешанное использование вызовов alarm() и sleep() - это плохая идея.
Постановка сигнала в очередь может вызывать задержу выполнения вызвавшего процесса на некоторое время.
СООТВЕТСТВИЕ СТАНДАРТАМ
SVr4, SVID, POSIX, X/OPEN, BSD 4.3
sleep - переход в режим ожидания на указанное количество секунд
СИНТАКСИС
#include <unistd.h>
unsigned int sleep(unsigned int seconds);
ОПИСАНИЕ
sleep() переводит текущий процесс в режим ожидания либо на seconds секунд, либо на время до получения сигнала, который не может быть проигнорирован.
ВОЗВРАЩАЕМЫЕ ЗНАЧЕНИЯ
Возвращается ноль, если указанное время истекло, или количество секунд, оставшихся до конца ожидания.
СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1
НАЙДЕННЫЕ ОШИБКИ
sleep() может применяться совместно с SIGALRM; использование вызовов alarm() и sleep() одновременно является крайне нежелательным.
Использование longjmp(), вызываемой из функции обработки сигнала, или изменение метода обработки сигнала SIGALRM во время режима ожидания может привести к непредсказуемым последствиям.
Пример
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#define TIMEOUT 5;
#define MAXTRIES 5
#define L_SIZE 100;
#define CTRL_G ‘\007’;
static int time_out;
static char answer[L_SIZE];
void catch(int sig)
{
time_out = 1;
putchar (CTRL_G);
}
char *quickreply (char *promt)
{
int nt;
static struct sigaction act, oact;
act.sa_handler = catch;
sigaction (SIGALRM, &act, &oact);
for (nt = 0; nt<MAXTRIES; nt++)
{
time_out = 0;
printf(“\n %s >”, promt);
alarm(TIMEOUT);
gets(answer);
alarm(0);//остановка таймера
if (!time_out) break;
}
sigaction(SIGALRM, &oact, NULL);
{ if (nt == MAXTRIES) return((char*)0);
else return (answer);
}
}
Функция осуществляет ввод данных от пользователя за заданное время
Пример
#include <unistd.h>
#include <signal.h>
Int n_times=0;
void p_action(int sig)
{printf(“родитель получил сигнал %d \n”, ++n_times);}
void c_action (int sig)
{printf(“сын получил сигнал %d \n”, ++n_times);}
main()
{
pid_t pid, ppid;
static struct sigaction pact, cact;
pact.sa_handler = p_action;
sigaction(SIGUSR1, &pact, NULL);
switch (pid = fork())
{
case -1: exit(-1); break;
case 0: cact.sa_handler = c_action;
sigaction(SIGUSR2, &cact, NULL);
ppid = getppid;
for (;;)
{
sleep(1);
kill(ppid, SIGUSR1);
pause();}
default:
for (;;)
{
pause();
sleep(1);
kill(pid, SIGUSR2);}
}
}
sigqueue - передает сигнал и данные процессу
