Книга: UNIX: взаимодействие процессов
Упражнения
Упражнения
1. Измените функции produce и consume из раздела 10.6 следующим образом. Поменяйте порядок двух вызовов Sem_wait в потребителе, чтобы возникла ситуация зависания (как описано в разделе 10.6). Затем добавьте вызов printf перед каждым Sem_wait, чтобы было ясно, какой из потоков ожидает изменения семафора. Добавьте еще один вызов printf после каждого Sem_wait, чтобы можно было определить, какой поток получил управление. Уменьшите количество буферов до двух, а затем откомпилируйте и выполните эту программу, чтобы убедиться, что она зависнет.
2. Предположим, что запущено четыре экземпляра программы, вызывающей функцию my_lock из листинга 10.10:
% lockpxsem & lockpxsem & lockpxsem & lockpxsem &
Каждый из четырех процессов запускается с значением initflag, равным 0, поэтому при вызове sem_open всегда указывается O_CREAT. Нормально ли это?
3. Что произойдет в предыдущем примере, если одна из четырех программ будет завершена после вызова my_lock, но перед вызовом my_unlock?
4. Что произошло бы с программой в листинге 10.22, если бы мы не инициализировали оба дескриптора значением –1?
5. Почему в листинге 10.22 мы сохраняем значение errno, а затем восстанавливаем его, вместо того чтобы написать просто:
if (sem->fd[0] >= 0) close(sem->fd[0]);
if (sem->fd[1] >= 0) close(sem->fd[1]);
6. Что произойдет, если два процесса вызовут нашу реализацию sem_open через FIFO (листинг 10.22) примерно одновременно, указывая флаг O_CREAT и начальное значение 5? Может ли канал быть инициализирован (неправильно) значением 10?
7. В связи с листингами 10.28 и 10.29 мы описали возможную ситуацию гонок в случае, если два процесса пытаются создать семафор примерно одновременно. Однако решение предыдущей задачи в листинге 10.22 не создавало ситуации гонок. Объясните это.
8. Стандарт Posix.1 указывает дополнительную возможность для функции semwait: она может прерываться перехватываемым сигналом и возвращать код EINTR. Напишите тестовую программу, которая определяла бы, есть ли такая возможность в вашей реализации.
Запустите эту тестовую программу с нашими реализациями, использующими FIFO (раздел 10.14), отображение в память (раздел 10.15) и семафоры System V (раздел 10.16).
9. Какая из трех реализаций sem_post этой главы является функцией типа async-signal-safe (табл. 5.1)?
10. Измените решение задачи о потребителе и производителе в разделе 10.6 так, чтобы для переменной mutex использовался тип pthread_mutex_t, а не семафор. Заметна ли разница в скорости работы программы?
11. Сравните быстродействие именованных семафоров (листинги 10.8 и 10.9) и размещаемых в памяти (листинг 10.11).
- 10.1.Введение
- 10.2. Функции sem_open, sem_close и sem_unlink
- 10.3. Функции sem_wait и sem_trywait
- 10.4. Функции sem_post и sem_getvalue
- 10.5. Простые примеры
- 10.6. Задача производителей и потребителей
- 10.7. Блокирование файлов
- 10.8. Функции sem_init и sem_destroy
- 10.9. Несколько производителей, один потребитель
- 10.10. Несколько производителей, несколько потребителей
- 10.11. Несколько буферов
- 10.12. Использование семафоров несколькими процессами
- 10.13. Ограничения на семафоры
- 10.14. Реализация с использованием FIFO
- 10.15. Реализация с помощью отображения в память
- 10.16. Реализация с использованием семафоров System V
- 10.17. Резюме
- Упражнения