- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания UNIX: взаимодействие процессов - Уильям Стивенс
Шрифт:
Интервал:
Закладка:
Семафоры Posix могут быть именованными или неименованными (размещаемыми в памяти). Именованные семафоры всегда могут использоваться отдельными процессами, тогда как размещаемые в памяти должны для этого изначально планироваться как разделяемые между процессами. Эти типы семафоров также отличаются друг от друга по живучести: именованные семафоры обладают по меньшей мере живучестью ядра, тогда как размещаемые в памяти обладают живучестью процесса.
Задача производителей и потребителей является классическим примером для иллюстрации использования семафоров. В этой главе первое решение состояло из одного потока-производителя и одного потока-потребителя; второе решение имело нескольких производителей и одного потребителя, а последнее решение допускало одновременную работу и нескольких потребителей. Затем мы показали, что классическая задача двойной буферизации является частным случаем задачи производителей и потребителей с одним производителем и одним потребителем.
В этой главе было приведено три примера возможной реализации семафоров Posix. Первый пример был самым простым, в нем использовались каналы FIFO, а большая часть забот по синхронизации ложилась на ядро (функции read и write). Следующая реализация использовала отображение файлов в память (аналогично реализации очередей сообщений Posix из раздела 5.8), а также взаимное исключение и условную переменную (для синхронизации). Последняя реализация была основана на семафорах System V и представляла собой, по сути, удобный интерфейс для работы с ними.
Упражнения
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).
ГЛАВА 11
Семафоры System V
11.1.Введение
В главе 10 мы описывали различные виды семафоров, начав с:
■ бинарного семафора, который может принимать только два значения: 0 и 1. По своим свойствам такой семафор аналогичен взаимному исключению (глава 7), причем значение 0 для семафора соответствует блокированию ресурса, а 1 — освобождению.
Далее мы перешли к более сложному виду семафоров:
■ семафор-счетчик, значение которого лежит в диапазоне от 0 до некоторого ограничения, которое, согласно Posix, не должно быть меньше 32767. Они использовался для подсчета доступных ресурсов в задаче о производителях и потребителях, причем значение семафора соответствовало количеству доступных ресурсов.
Для обоих типов семафоров операция wait состояла в ожидании изменения значения семафора с нулевого на ненулевое и последующем уменьшении этого значения на 1. Операция post увеличивала значение семафора на 1, оповещая об этом все процессы, ожидавшие изменения значения семафора.
Для семафоров System V определен еще один уровень сложности:
■ набор семафоров-счетчиков — один или несколько семафоров, каждый из которых является счетчиком. На количество семафоров в наборе существует ограничение (обычно порядка 25 — раздел 11.7). Когда мы говорим о семафоре System V, мы подразумеваем именно набор семафоров-счетчиков, а когда говорим о семафоре Posix, подразумевается ровно один семафор-счетчик.
Для каждого набора семафоров ядро поддерживает следующую информационную структуру, определенную в файле <sys/sem.h>:
struct semid_ds {
struct ipc_perm sem_perm; /* разрешения на операции */
struct sem *sem_base; /*указатель на массив семафоров в наборе */
ushort sem_nsems; /* количество семафоров в наборе */
time_t sem_otime; /* время последнего вызова semop(); */
time_t sem_ctime; /* время создания последнего IPC_SET */
};
Структура ipc_perm была описана в разделе 3.3. Она содержит разрешения доступа для данного семафора.
Структура sem представляет собой внутреннюю структуру данных, используемую ядром для хранения набора значений семафора. Каждый элемент набора семафоров описывается так:
struct sem {
ushort_t semval; /* значение семафора, неотрицательно */
short sempid; /* PID последнего процесса, вызвавшего semop(), SETVAL, SETALL */
ushort_t semncnt; /* количество ожидающих того, что значение семафора превысит текущее */
ushort_t semzcnt; /* количество ожидающих того, что значение семафора станет равным 0*/
};
Обратите внимание, что sem_base представляет собой указатель на массив структур типа sem — по одному элементу массива на каждый семафор в наборе.
Помимо текущих значений всех семафоров набора в ядре хранятся еще три поля данных для каждого семафора: идентификатор процесса, изменившего значение семафора последним, количество процессов, ожидающих увеличения значения семафора, и количество процессов, ожидающих того, что значение семафора станет нулевым.
ПРИМЕЧАНИЕ
В стандарте Unix 98 данная структура не имеет имени. Приведенное выше имя (sem) взято из реализации System V.
Любой конкретный семафор в ядре мы можем воспринимать как структуру semid_ds, указывающую на массив структур sem. Если в наборе два элемента, мы получим картину, изображенную на рис. 11.1. На этом рисунке переменная sem_nsems имеет значение 2, а каждый из элементов набора идентифицируется индексом ([0] или [1]).
Рис. 11.1. Структуры данных ядра для набора семафоров из двух элементов
11.2. Функция semget
Функция semget создает набор семафоров или обеспечивает доступ к существующему.
#include <sys/sem.h>
int semget(key_t key, int nsems, int oflag);
/* Возвращает неотрицательный идентификатор в случае успешного завершения, –1 – в случае ошибки */
Эта функция возвращает целое значение, называемое идентификатором семафора, которое затем используется при вызове функций semop и semctl.
Аргумент nsems задает количество семафоров в наборе. Если мы не создаем новый набор, а устанавливаем доступ к существующему, этот аргумент может быть нулевым. Количество семафоров в уже созданном наборе изменить нельзя.
Аргумент oflag представляет собой комбинацию констант SEM_R и SEM_A из табл. 3.3. Здесь R обозначает Read (чтение), а А — Alter (изменение). К этим константам можно логически прибавить IPC_CREAT или IPC_CREAT | IPC_EXCL, о чем мы уже говорили в связи с рис. 3.2.
При создании нового семафора инициализируются следующие поля структуры semid_ds: