Средства межпроцессного взаимодействия (IPC) в ОС LINUX. Семафоры и разделяемая память. Ненадежные сигналы, страница 2

/* Блокировка сигнала SIGINT*/

if( signo != SIGINT )

{

sigaddset( &act.sa_mask, SIGINT );

}

/* Установка диспозиции */

if( sigaction( signo, &act, &old_act ) < 0)

{

return ( SIG_ERR );

}

return (old_act.sa_handler);

}

/* Обработчик сигнала SIGINT */

void sigint_handler( int signo )

{

printf( "SIGINT is handled!!!\n" );

}

/* Обработчик сигнала SIGUSR1 */

void sigusr1_handler( int signo )

{

raise( SIGINT );

printf( "Wait...\n" );

sleep( 20 );

printf( "SIGUSR1 is handled!!!\n" );

}

/* Обработчик сигнала SIGUSR2 */

void sigusr2_handler( int signo )

{

printf( "SIGUSR2 is handled!!!\n" );

}

Результаты работы программы.

# kill -s SIGINT 6725678

SIGINT is handled!!!

# kill -s SIGUSR2 6725678

SIGUSR2 is handled!!!

# kill -s SIGUSR1 6725678

Wait...

SIGUSR1 is handled!!!

SIGINT is handled!!!

Из обработчика сигнала SIGUSR1 процессом посылается сигнал SIGINT самому себе с помощью функции raise(), но  SIGINT ожидает завершения обработки SIGUSR1, потому что так установлена маска.

Для сигнала SIGUSR2 маска не установлена, поэтому он может прервать обработку сигнала SIGUSR1:

# kill -s SIGUSR1 6725678

# kill -s SIGUSR2 6725678

SIGUSR2 is handled!!!

SIGUSR1 is handled!!!

SIGINT is handled!!!

            Преимущества надежных сигналов по сравнению с ненадежным:

·  Диспозиция устанавливается только один раз, и диспозицию не нужно устанавливать каждый раз в функции-обработчике.

·  При установке диспозиции, можно указать какие сигналы будут блокироваться на время обработки конкретного сигнала, это значительно увеличивает надежность обработки сигнала.


3. Неименованные каналы.

В следующей программе реализовано взаимодействие двух родственных процессов с помощью неименованного канала.

Процесс-потомок открывает на чтение произвольный текстовый файл и записывает считываемую из него информацию в созданный неименованный канал. Процесс-родитель считывает из канала информацию и записывает в новый текстовый файл.

Имена входного и выходного файлов задаются из командной строки.

Листинг 3. pipe.c.

/*

* Неименованные каналы

*/

#include <stdlib.h>

#include <unistd.h>

#include <stdio.h>

#include <fcntl.h>

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

{

/* Проверка аргументов коммандной сроки */

if( argc < 3 )

{

printf( "Father: Error - command line arg!!!\n" );

exit(1);

}

int    file_ds[2];

int    src_file;

int    dst_file;

char   buf[1];

/* Создаем pipe */

if( pipe(file_ds) < 0 )

{

printf( "Father: Create pipe error!!!\n" );

exit(1);

}

printf( "Father: pipe created.\n" );

/* Создаем новый процесс */

pid_t chld_pid;

chld_pid = fork();

switch( chld_pid )

{

case -1:

{

printf( "Father: Create pocess error!!!\n" );

exit(2);

break;

}

case 0:

{

src_file = open( argv[1], O_RDONLY );

if( src_file < 0 )

{

printf( "Son: Error open file %s!!!\n", argv[1] );

exit(3);

}

printf( "Son: File %s is open!!!\n", argv[1] );

/* Чтение текстового файла и запись в канал */

close( file_ds[0] );

while( read(src_file, buf, 1) == 1 )

{

if( write( file_ds[1], buf,1 ) != 1 )

{

printf( "Son: error write to pipe!!!\n" );

break;

}

}

/* Закрытие дескрипторов */

close( src_file );

close( file_ds[1] );

return EXIT_SUCCESS;

}

default:

break;

}

/* Открываем файл для вывода */

dst_file = open( argv[2], O_WRONLY );

if( dst_file == -1 )

{

printf( "Father: Error open file %s!!!\n", argv[2] );

exit(4);

}

printf( "Father: File %s is open!!!\n", argv[2] );

/* Чтение из канала и вывод в файл */

// Нужно закрыть канал для записи, иначе чтение не завершится

close( file_ds[1] );

while( read(file_ds[0], buf, 1) == 1 )

{

write(dst_file, buf, 1);

}

/* Закрытие дескрипторов */

close( file_ds[0] );

close( dst_file );

return EXIT_SUCCESS;

}

В процессе-родителе создается неименованный канал, посредством системного вызова pipe(2), дочерние процессы получают доступ к дескрипторам созданного канала.