Для работы с разделяемой памятью используются системные вызовы:
· shmget() создает новый сегмент разделяемой памяти или находит существующий сегмент с тем же ключом;
· shmat() подключает сегмент с указанным описателем к виртуальной памяти обращающегося процесса;
· shmdt() отключает от виртуальной памяти ранее подключенный к ней сегмент с указанным виртуальным адресом начала;
· shmctl() служит для управления разнообразными параметрами, связанными с существующим сегментом.
Прототипы перечисленных системных вызовов описаны в файлах:
#include <sys/ipc.h> #include <sys/shm.h>
После того, как сегмент разделяемой памяти подключен к виртуальной памяти процесса, этот процесс может обращаться к соответствующим элементам памяти с использованием обычных машинных команд чтения и записи.
Системный вызов
int shmid = shmget (key_t key, size_t size, int flag);
на основании параметра size определяет желаемый размер сегмента в байтах. Если в таблице разделяемой памяти находится элемент, содержащий заданный ключ, и права доступа не противоречат текущим характеристикам обращающегося процесса, то значением системного вызова является идентификатор существующего сегмента. В противном случае создается новый сегмент с размером не меньше установленного в системе минимального размера сегмента разделяемой памяти и не больше установленного максимального размера. Создание сегмента не означает немедленного выделения под него основной памяти и это действие откладывается до выполнения первого системного вызова подключения сегмента к виртуальной памяти некоторого процесса. Флаги IPC_CREAT и IPC_EXCL аналогичны рассмотренным выше.
Подключение сегмента к виртуальной памяти выполняется путем обращения к системному вызову shmat():
void *virtaddr = shmat(int shmid, void *daddr, int flags);
Параметр shmid - это ранее полученный идентификатор сегмента, а daddr - желаемый процессом виртуальный адрес, который должен соответствовать началу сегмента в виртуальной памяти. Значением системного вызова является фактический виртуальный адрес начала сегмента. Если значением daddr является NULL, ядро выбирает наиболее удобный виртуальный адрес начала сегмента.
Флаги системного вызова shmat():
SHM_RDONLY
ядро подключает участок памяти только для чтения.
SHM_RND
определяет, если возможно, способ обработки ненулевого значения daddr.
Для отключения сегмента от виртуальной памяти используется системный вызов shmdt():
int shmdt(*daddr);
где daddr - это виртуальный адрес начала сегмента в виртуальной памяти, ранее полученный от системного вызова shmat().
Системный вызов shmctl()
int shmctl (int shmid, int command, struct shmid_ds *shm_stat);
по синтаксису и назначению полностью аналогичен msgctl().
Варианты заданий
1. Два дочерних процесса выполняют некоторые циклы работ, передавая после окончания очередного цикла через очередь сообщений родительскому процессу очередные четыре строки некоторого стихотворения, при этом первый процесс передает нечетные четырехстишья, второй - четные. Циклы работ процессов не сбалансированы по времени. Родительский процесс компонует из передаваемых фрагментов законченное стихотворение и выводит его по завершении работы обоих процессов. Решить задачу с использованием аппарата семафоров.
2. Два дочерних процесса выполняют некоторые циклы работ, передавая после окончания очередного цикла через один и тот же сегмент разделяемой памяти родительскому процессу очередные четыре строки некоторого стихотворения, при этом первый процесс передает нечетные четырехстишья, второй - четные. Циклы работ процессов не сбалансированы по времени. Родительский процесс компонует из передаваемых фрагментов законченное стихотворение и выводит его по завершении работы обоих процессов. Решить задачу с использованием аппарата семафоров.
3. Четыре дочерних процесса выполняют некоторые циклы работ, передавая после окончания очередного цикла через один и тот же сегмент разделяемой памяти родительскому процессу очередную строку некоторого стихотворения, при этом первый процесс передает 1-ю, 5-ю, 9-ю и т.д. строки, второй - 2-ю, 6-ю, 10-ю и т.д. строки, третий - 3-ю, 7-ю, 11-ю и т.д. строки, четвертый - 4-ю, 8-ю, 12-ю и т.д. строки. Циклы работ процессов не сбалансированы по времени. Родительский процесс компонует из передаваемых фрагментов законченное стихотворение и выводит его по завершении работы всех процессов. Решить задачу с использованием аппарата семафоров.
4. Программа моделирует работу примитивной СУБД, хранящей единственную таблицу в оперативной памяти. Выполняя некоторые циклы работ, K порожденных процессов посредством очереди сообщений передают родительскому процессу номер строки, которую нужно удалить из таблицы. Родительский процесс выполняет указанную операцию и возвращает содержимое удалённой строки.
5. Программа моделирует работу примитивной СУБД, хранящей единственную таблицу в оперативной памяти. Выполняя некоторые циклы работ, K порожденных процессов посредством очереди сообщений передают родительскому процессу номер строки и её содержимое, на которое нужно изменить хранящиеся в ней данные. Родительский процесс выполняет указанную операцию и возвращает старое содержимое изменённой строки.
6. Программа моделирует работу примитивной СУБД, хранящей единственную таблицу в оперативной памяти. Выполняя некоторые циклы работ, K порожденных процессов посредством очереди сообщений передают родительскому процессу содержимое строки, которую нужно добавить в таблицу. Родительский процесс проверяет, нет ли в таблице такой строки, и, если нет, добавляет строку и возвращает количество хранящихся в таблице строк.
7. Четыре дочерних процесса выполняют некоторые циклы работ, передавая после окончания очередного цикла через очередь сообщений родительскому процессу очередную строку некоторого стихотворения, при этом первый процесс передает 1-ю, 5-ю, 9-ю и т.д. строки, второй - 2-ю, 6-ю, 10-ю и т.д. строки, третий - 3-ю, 7-ю, 11-ю и т.д. строки, четвертый - 4-ю, 8-ю, 12-ю и т.д. строки. Циклы работ процессов не сбалансированы по времени. Родительский процесс компонует из передаваемых фрагментов законченное стихотворение и выводит его по завершении работы всех процессов. Решить задачу с использованием аппарата семафоров.
8. Родительский процесс помещает в сегмент разделяемой памяти имена программ из предыдущих лабораторных работ, которые могут быть запущены. Выполняя некоторые циклы работ, порожденные процессы случайным образом выбирают имена программ из таблицы сегмента разделяемой памяти, запускают эти программы, и продолжают свою работу. Посредством аппарата семафоров должно быть обеспечено, чтобы не были одновременно запущены две программы от одного процесса. В процессе работы через очередь сообщений родительский процесс информируется, какие программы и от имени кого запущены.
9. Родительский процесс помещает в сегмент разделяемой памяти имена программ из предыдущих лабораторных работ, которые могут быть запущены. Выполняя некоторые циклы работ, порожденные процессы случайным образом выбирают имена программ из таблицы сегмента разделяемой памяти, запускают эти программы, и продолжают свою работу. Посредством аппарата семафоров должно быть обеспечено, чтобы не были одновременно запущены две одинаковые программы. В процессе работы через очередь сообщений родительский процесс информируется, какие программы и от имени кого запущены.
10. Программа моделирует работу монитора обработки сообщений. Порожденные процессы, обладающие различными приоритетами и выполняющие некоторые циклы работ, посредством очереди сообщений передают родительскому процессу имена программ из предыдущих лабораторных работ, которые им должны быть запущены. Родительский процесс, обрабатывая сообщения в соответствии с их приоритетами, следит, чтобы одновременно было запущено не более трех программ.
Контрольные вопросы
1. В чем разница между двоичным и общим семафорами?
2. Чем отличаются P() и V()-операции от обычных операций увеличения и уменьшения на единицу?
3. Для чего служит набор программных средств IPC?
4. Для чего введены массовые операции над семафорами в ОС UNIX?
5. Каково назначение механизма очередей сообщений?
6. Какие операции над семафорами существуют в ОС UNIX?
7. Каково назначение системного вызова msgget()?
8. Какие условия должны быть выполнены для успешной постановки сообщения в очередь?
9. Как получить информацию о владельце и правах доступа очереди сообщений?