Чтение онлайн

на главную - закладки

Жанры

Основы программирования в Linux
Шрифт:

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <sys/sem.h>

#include "semun.h"

static int set_semvalue(void);

static void del_semvalue(void);

static int semaphore_p(void);

static int semaphore_v(void);

static int sem_id;

int main(int argc, char *argv[]) {

 int i;

 int pause_time;

 char op_char = 'О';

 srand((unsigned int)getpid);

 sem_id = semget((key_t)1234, 1, 0666 | IPC_CREAT);

 if (argc >1) {

if (!set_semvalue) {

fprintf(stderr, "Failed to initialize semaphore\n");

exit(EXIT_FAILURE);

}

op_char = 'X';

sleep(2);

 }

2. Далее

следует цикл, в котором 10 раз выполняется вход в критическую секцию и выход из нее. Вы сначала выполняете вызов функции
semaphore_p
, которая заставляет семафор ждать, когда эта программа будет готова войти в критическую секцию.

 for (i = 0; i < 10; i++) {

if (!semaphore_p) exit(EXIT_FAILURE);

printf("%c", op_char);

fflush(stdout);

pause_time = rand % 3;

sleep(pause_time);

printf("%c", op_char);

fflush(stdout);

3. После критической секции вы вызываете функцию

semaphore_v
, которая освобождает семафор перед повторным проходом цикла
for
после ожидания в течение случайного промежутка времени. После цикла выполняется вызов функции
del_semvalue
для очистки кода.

if (!semaphore_v) exit(EXIT_FAILURE);

pause_time = rand % 2;

sleep(pause_time);

 }

 printf("\n%d - finished\n", getpid);

 if (argc > 1) {

sleep(10);

del_semvalue;

 }

 exit(EXIT_SUCCESS);

}

4. Функция

set_semvalue
инициализирует семафор с помощью команды
SETVAL
в вызове
semctl
. Это следует сделать перед использованием семафора.

static int set_semvalue(void) {

 union semun sem_union;

 sem_union.val = 1;

 if (semctl(sem_id, 0, SETVAL, sem_union) == -1) return(0);

 return(1);

}

5. У

функции
del_semvalue
почти та же форма за исключением того, что в вызове
semctl
применяется команда
IPC_RMID
для удаления ID семафора.

static void del_semvalue(void) {

 union semun sem_union;

 if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1)

fprintf(stderr, "Failed to delete semaphore\n");

}

6. Функция semaphore_p изменяет счетчик семафора на -1. Это операция ожидания или приостановки процесса.

static int semaphore_p(void) {

 struct sembuf sem_b;

 sem_b.sem_num = 0;

 sem_b.sem_op = -1; /* P */

 sem_b.sem_flg = SEM_UNDO;

 if (semop(sem_id, &sem_b, 1) == -1) {

fprintf(stderr, "semaphore_p failed\n");

return(0);

 }

 return(1);

}

7. Функция

semaphore_v
аналогична за исключением задания элемента
sem_op
структуры
sembuf
, равного 1. Это операция "освобождения", в результате которой семафор снова становится доступен.

static int semaphore_v(void) {

 struct sembuf sem_b;

 sem_b.sem_num = 0;

 sem_b.sem_op = 1; /* V */

 sem_b.sem_flg = SEM_UNDO;

 if (semop(sem_id, &sem_b, 1) == -1) {

fprintf(stderr, "semaphore_v failed\n");

return(0);

 }

 return(1);

}

Обратите внимание на то, что эта простая программа разрешает существование единственного двоичного семафора для каждой программы, хотя можно было бы увеличить количество, передав переменную семафора при необходимости. Обычно одного бинарного семафора достаточно.

Вы можете протестировать вашу программу, запустив ее несколько раз. В первый раз вы передадите параметр, чтобы сообщить программе о том, что она отвечает за создание и удаление семафора. У других экземпляров выполняющейся программы не будет параметра.

Далее приведен примерный вывод для двух запущенных экземпляров программы:

$ cc sem1.с -о sem1

$ ./sem1 1 &

[1] 1082

$ ./sem1

Поделиться:
Популярные книги

Телохранитель Цесаревны

Зот Бакалавр
5. Герой Империи
Фантастика:
фэнтези
боевая фантастика
5.25
рейтинг книги
Телохранитель Цесаревны

Наследие Маозари 9

Панежин Евгений
9. Наследие Маозари
Фантастика:
попаданцы
постапокалипсис
рпг
сказочная фантастика
6.25
рейтинг книги
Наследие Маозари 9

Память

Буджолд Лоис Макмастер
10. Сага о Форкосиганах
Фантастика:
научная фантастика
9.41
рейтинг книги
Память

Эволюционер из трущоб. Том 10

Панарин Антон
10. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Эволюционер из трущоб. Том 10

Анти-Ксенонская Инициатива

Вайс Александр
7. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
космоопера
5.00
рейтинг книги
Анти-Ксенонская Инициатива

Мы друг друга не выбирали

Кистяева Марина
1. Мы выбираем...
Любовные романы:
остросюжетные любовные романы
прочие любовные романы
современные любовные романы
5.00
рейтинг книги
Мы друг друга не выбирали

Адвокат империи

Карелин Сергей Витальевич
1. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
фэнтези
5.75
рейтинг книги
Адвокат империи

Глэрд IX: Легионы во Тьме

Владимиров Денис
9. Глэрд
Фантастика:
боевая фантастика
попаданцы
фэнтези
5.00
рейтинг книги
Глэрд IX: Легионы во Тьме

Идеальный мир для Лекаря 21

Сапфир Олег
21. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 21

Я Гордый часть 2

Машуков Тимур
2. Стальные яйца
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я Гордый часть 2

Мастер 8

Чащин Валерий
8. Мастер
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Мастер 8

Воин-Врач

Дмитриев Олег
1. Воин-Врач
Фантастика:
попаданцы
альтернативная история
историческое фэнтези
6.00
рейтинг книги
Воин-Врач

Войсковые разведчики в Афгане. Записки начальника разведки дивизии

Кузьмин Николай Павлович
1. Афган: Последняя война СССР
Документальная литература:
биографии и мемуары
5.00
рейтинг книги
Войсковые разведчики в Афгане. Записки начальника разведки дивизии

Неудержимый. Книга XXX

Боярский Андрей
30. Неудержимый
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Неудержимый. Книга XXX