Главная страница  Взаимодействие нетривиальных процессов 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 [ 35 ] 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

согласно табл. 5.1, функция write принадлежит к группе async-signal-safe, поэтому она может вызываться из обработчика сигналов. Программа приведена в листинге 5.12.

Листинг 5.12.1/1спользование уведомления с помощью сигнала и канала

pxmsg/mqnotifysigS.c

1 #include unpipcli

2 int pipefd[2]:

3 static void sig usrl(int):

4 int

5 maindnt argc, char **argv)

7 1nt nfds:

8 char c:

9 fd set rset:

10 mqd t mqd:

11 void *buff-,

12 ssize t n:

13 struct mq attr attr;

14 struct sigevent sigev:

15 if (argc != 2)

16 err quit( usage: mqnotifysigS <name> ):

17 /* открытие очереди, получение атрибутов, выделение буфера */

18 mqd = Mq open(argv[l]. 0 ROONLY 0 NONBLOCK):

19 Mq getattr(mqd, &attr):

20 buff = Malloc(attr.mq msgsize);

21 Pipe(pipefd);

22 /* установка обработчика, включение уведомления */

23 Signal(SIGUSRl, sig usrl);

24 sigev.sigev notify = SIGEV SIGNAL;

25 sigev.sigev signo = SIGUSRl;

26 Mq notify(mqd. &sigev);

27 FO ZERO(&rset);

28 for ( ; : ) {

29 FO SET(pipefd[0]. &rset):

30 nfds = Select(pipefd[0] + 1, &rset. NULL, NULL, NULL);

31 if (FOJSSET(pipefd[0]. &rset)) {

32 Read(pipefd[0]. &c. 1):

33 Mq notify(mqd, &sigev): /* перерегистрируемся */

34 while ( (n - mq receive(mqd, buff, attr.mq msgsize. NULL)) >= 0) {

35 printf( read %й bytes\n . (long) n);

36 }

37 if (errno != EAGAIN)

38 err sys( mq receive error ):

39 }

40 }

41 exit(O):

42 )



43 static void

44 sig usrl(int signo)

45 {

46 Write(pipefd[l]. . 1): /* один байт - О */

47 return;

48 }

Создание канала

21 Мы создаем канал, в который обработчик сигнала произведет запись, когда будет получено уведомление о поступлении сообщения в очередь. Это пример использования канала внутри одного процесса.

Вызов select

27-40 Мы инициализируем набор дескрипторов rset и при каждом проходе цикла включаем бит, соответствующий дескриптору pipefd[0] (открытый на считывание конец канала). Затем мы вызываем функцию sel ect, ожидая получения единственного дескриптора, хотя в типичном приложении именно здесь осуществлялось бы размножение дескрипторов одного из концов канала. Когда появляется возможность читать из канала, мы перерегистрируемся на уведомление и считываем все доступные сообщения.

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

43-48 Единственное, что делает обработчик сигнала, - записывает в канал 1 байт. Как мы уже отмечали, эта операция относится к разрешенным для асинхронных обработчиков.

Пример: запуск нового потока

Альтернативой снятию блокировки сигналом является присваивание si gev noti fy значения SIGEV THREAD, что приводит к созданию нового потока. Функция, указанная в sigev notifу function, вызывается с параметром sigev va1ue. Атрибуты нового канала указываются переменной sigev notify attributes, которая может быть и нулевым указателем, если нас устраивают устанавливаемые по умолчанию атрибуты. Текст программы приведен в листинге 5.13.

Листинг 5.13. Функция mq notify, запускающая новый программный поток

pxmsg/mqnotifythreadl.c

1 #include unpipc.h

2 niqd t mqd;

3 struct mq attr attr:

4 struct sigevent sigev:

5 static void notify thread(union sigval); /* наш поток */

6 int

7 mainCint argc. char **argv)

9 if (argc != 2)

10 err quit( usage: mqnotifythreadl <name> ):

11 mqd = Mq open(argv[l]. 0 ROONLY 0 NONBLOCK): продолжение



Листинг 5.13 (продолжение)

12 Mq getattr(niqd, &attr);

13 sigev.s1gev notify = SIGEV THREAD:

14 sigev.sigev value.sival ptr = NULL:

15 sigev.sigev notify function = not ify tli read;

16 sigev.sigev notify attributes = NULL:

17 Mq notify(mqd. &sigev);

18 for ( ; : )

19 pauseO: /* новый поток делает все */

20 exit(O):

21 }

22 Static void

23 notify tliread(union sigval arg)

24 {

25 ssize t n:

26 void *buff:

27 printf( notify tliread started\n ):

28 buff = Mailoc(attr.mq msgsize):

29 Mq notify(mqd, &sigev): /* перерегистрируемся */

30 wliile ( (n = niq receive(mqd. buff, attr.mqmsgsize. NULL)) >= 0) {

31 pnntf( read Id bytes\n . (long) n):

32 }

33 if (errno != EAGAIN)

34 err sys( niq receive error ):

35 free(buff):

36 ptliread exit(NULL):

37 }

Мы задаем нулевой указатель в качестве аргумента нового потока (si gev val ue), поэтому функции start нового потока ничего не передается. Мы могли бы передать указатель на дескриптор, вместо того чтобы декларировать его как глобальный, но новому потоку все равно нужно получать атрибуты очереди сообщений и структуру sigev (для перерегистрации). Мы также указываем нулевой указатель в качестве атрибутов нового потока, поэтому используются установки по умолчанию. Новые потоки создаются как неприсоединенные (detached threads).

ПРИМЕЧАНИЕ -

К сожалению, ни одна из использовавшихся для проверки примеров систем (Solaris 2.6 и Digital Unix 4.0В) не поддерживает SIGEVTHREAD. Обе они допускают только два значения sigev notify: SIGEV N0NE и SIGEV SIGNAL.

5.7. Сигналы реального времени Posix

За прошедшие годы сигналы в Unix много раз претерпевали революционные изменения.

1. Модель сигналов, предлагавшаяся в Unix Version 7 (1978), была ненадежной. Сигналы могли быть потеряны, и процессу было трудно отключить отдельные сигналы при выполнении отдельных участков кода.



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 [ 35 ] 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования.