//pxsem/testeintr.c
1 #include "unpipc.h"
2 #define NAME "testeintr"
3 static void sig_alrm(int);
4 int
5 main(int argc, char **argv)
6 {
7 sem_t *sem1, sem2;
8 /* именованный семафор */
9 sem_unlink(Px_ipc_name(NAME));
10 sem1 = Sem_open(Px_ipc_name(NAME), O_RDWR | O_CREAT | О_EXCL,
11 FILE_MODE, 0);
12 Signal(SIGALRM, sig_alrm);
13 alarm(2);
14 if (sem_wait(sem1) == 0)
15 printf("sem_wait returned 0?\n");
16 else
17 err_ret("sem_wait error");
18 Sem_close(sem1);
19 /* размещаемый в памяти семафор */
20 Sem_init(&sem2, 1, 0);
21 alarm(2);
22 if (sem_wait(&sem2) == 0)
23 printf("sem_wait returned 0?\n");
24 else
25 err_ret("sem_wait error");
26 Sem_destroy(&sem2);
27 exit(0);
28 }
29 static void
30 sig_alrm(int signo)
31 {
32 printf("SIGALRM caught\n");
33 return;
34 }
Реализация с использованием FIFO возвращает EINTR, поскольку sem_wait блокируется в вызове read, который должен возвращать такую ошибку. Реализация с использованием отображения в память ошибки не возвращает, поскольку sem_wait блокируется в вызове pthread_cond_wait, а эта функция не возвращает такой ошибки. Реализация с использованием семафоров System V возвращает ошибку EINTR, поскольку sem_wait блокируется в вызове semop, которая возвращает эту ошибку.
9. Реализация с использованием каналов (листинг 10.25) является защищенной, поскольку таковой является операция write. Реализация с отображением в память защищенной не является, поскольку функции pthread_XXX не являются защищенными и не могут вызываться из обработчика сигналов. Реализация с семафорами System V (листинг 10.41) также не является защищенной, поскольку semop не является защищенной функцией согласно Unix 98.
Глава 11
1. Нужно изменить только одну строку:
< semid = Semget(Ftok(argv[optind], 0), 0, 0);
…
2. Вызов ftok вернет ошибку, что приведет к завершению работы обертки Ftok. Функция my_lock могла бы вызывать ftok перед semget, проверять, не возвращается ли ошибка ENOENT, а затем создавать файл, если он не существует.
Глава 12
1. Размер файла увеличится еще на 4096 байт (до 36864), но обращение к новому концу файла (36863) может привести к отправке сигнала SIGSEGV, поскольку размер области отображения в памяти равен 32768 байт. Причина, по которой мы говорим «может», а не «должен», — в неопределенности размера страницы памяти.
2. На рис. Г.1 показана схема с очередью сообщений System V, а на рис. Г.2 — с очередью сообщений Posix. Вызовы memcpy в отправителе происходят внутри функций mq_send (листинг 5.26), а в получателе — внутри mq_receive (листинг 5.28).
Рис. Г.1. Отправка сообщений в очередь System V
Рис. Г.2. Отправка сообщений через очередь Posix, реализованную с mmap
3. Любой вызов read для /dev/zero возвращает запрошенное количество нулей. Данные, помещаемые в этот файл, попросту сбрасываются (аналогично /dev/null).
4. В результате в файле получится 4 байта — все нули (предполагается 32-разрядное целое).
5. В листинге Г.7 приведен текст нашей программы.
//shm/svmsgread.c
1 #include "unpipc.h"
2 #define MAXMSG (8192 + sizeof(long))
3 int
4 main(int argc, char **argv)
5 {
6 int pipe1[2], pipe2[2], mqid;
7 char c;
8 pid_t childpid;
9 fd_set rset;
10 ssize_t n, nread;
11 struct msgbuf *buff;
12 if (argc != 2)
13 err_quit("usage: svmsgread
14 Pipe(pipe1); /* двусторонняя связь */
15 Pipe(pipe2);
16 buff = My_shm(MAXMSG); /* неименованная разделяемая память */
17 if ((childpid = Fork()) == 0) {
18 Close(pipe1[1]); /* child */
19 Close(pipe2[0]);