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

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

Жанры

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

Следующая пара функций управляет значением семафора и объявляется следующим образом.

#include <semaphore.h>

int sem_wait(sem_t* sem);

int sem_post(sem_t* sem);

Обе они принимают указатель на объект-семафор, инициализированный вызовом

sem_init
.

Функция

sem_post
атомарно увеличивает значение семафора на 1. Атомарно в данном случае означает, что если два потока одновременно пытаются увеличить значение единственного семафора на 1, они не мешают друг другу, как в случае двух программ, которые читают, увеличивают и записывают значение в файл в одно и то же время. Если обе программы пытаются увеличить значение на 1, семафор всегда будет корректно увеличивать значение на 2.

Функция

sem_wait
атомарно уменьшает значение семафора на единицу, но всегда ждет до тех пор, пока сначала счетчик семафора не получит ненулевое значение. Таким образом, если вы вызываете
sem_wait
для семафора со значением 2, поток продолжит выполнение, а семафор будет уменьшен до 1. Если
sem_wait
вызывается для семафора со значением 0, функция будет ждать до тех пор, пока какой-нибудь другой поток не увеличит значение, и оно станет ненулевым. Если оба потока ждут в функции
sem_wait
, чтобы один и тот же семафор стал ненулевым, и он увеличивается когда-нибудь третьим потоком, только один из двух ждущих потоков получит возможность уменьшить семафор и продолжиться; другой поток так и останется ждущим. Эта атомарная способность "проверить и установить" в одной функции и делает семафор столь ценным.

Примечание

Есть и другая функция семафора

sem_trywait
— это неблокирующий партнер
sem_wait
. Мы не будем ее обсуждать в книге в дальнейшем, дополнительную информацию см. в интерактивном справочном руководстве.

Последняя функция семафоров —

sem_destroy
. Она очищает семафор, когда вы закончили работу с ним, и объявляется следующим образом:

#include <semaphore.h>

int sem_destroy(gem_t* sem);

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

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

А теперь выполните упражнение 12.3.

Упражнение 12.3. Семафор потока

Текст этой программы thread3.c также основан на тексте программы thread1.c. Поскольку изменения значительны, мы приводим новый вариант полностью.

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

#include <string.h>

#include <pthread.h>

#include <semaphore.h>

void *thread_function(void *arg);

sem_t bin_sem;

#define WORK_SIZE 1024

char work_area[WORK_SIZE];

int main {

 int res;

 pthread_t a_thread;

 void *thread result;

 res = sem_init(&bin_sem, 0, 0);

 if (res != 0) {

perror("Semaphore initialization failed");

exit(EXIT_FAILURE);

 }

 res = pthread_create(&a_thread, NULL, thread_function, NULL);

 if (res != 0) {

perror("Thread creation failed");

exit(EXIT_FAILURE);

 }

 printf("Input some text. Enter 'end' to finish\n");

 while (strncmp("end", work_area, 3) != 0) {

fgets(work_area, WORK_SIZE, stdin);

sem_post(&bin_sem);

 }

 printf("\nWaiting for thread to finish...\n");

 res = pthread_join(a_thread, &thread_result);

 if (res != 0) {

perror("Thread join failed");

exit(EXIT_FAILURE);

 }

 printf("Thread joined\n");

 sem_destroy(&bin_sem);

 exit(EXIT_SUCCESS);

}

void *thread function(void *arg) { sem_wait(&bin_sem);

 while(strncmp("end", work area, 3) != 0) {

printf("You input %d characters\n", strlen(work_area)-1);

sem_wait(&bin_sem);

 }

 pthread_exit(NULL);

}

Первое важное изменение — включение файла semaphore.h для обеспечения доступа к функциям семафоров. Далее вы объявляете семафор и несколько переменных и инициализируете семафор перед тем, как создать новый поток.

sem_t bin_sem;

#define WORK_SIZE 1024

char work_area[WORK_SIZE];

int main {

 int res;

 pthread_t a_thread;

 void *thread_result;

 res = sem_init(&bin_sem, 0, 0);

 if (res != 0) {

perror("Semaphore initialization failed");

exit(EXIT_FAILURE);

 }

Обратите внимание на то, что начальное значение семафора равно 0.

В функции

main
, после того как вы запустили новый поток, вы читаете некоторый текст с клавиатуры, загружаете вашу рабочую область и затем наращиваете счетчик семафора с помощью
sem_post
:

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

Первый среди равных. Книга X

Бор Жорж
10. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Первый среди равных. Книга X

Мастер порталов

Лисина Александра
8. Гибрид
Фантастика:
боевая фантастика
попаданцы
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
Мастер порталов

Шайтан Иван 6

Тен Эдуард
6. Шайтан Иван
Фантастика:
попаданцы
альтернативная история
историческое фэнтези
7.00
рейтинг книги
Шайтан Иван 6

Моров. Том 3

Кощеев Владимир
2. Моров
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Моров. Том 3

Я до сих пор не князь. Книга XVI

Дрейк Сириус
16. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я до сих пор не князь. Книга XVI

Вернувшийся: Посол. Том IV

Vector
4. Вернувшийся
Фантастика:
космическая фантастика
киберпанк
5.00
рейтинг книги
Вернувшийся: Посол. Том IV

На границе империй. Том 7

INDIGO
7. Фортуна дама переменчивая
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
6.75
рейтинг книги
На границе империй. Том 7

Хозяин оков V

Матисов Павел
5. Хозяин Оков
Фантастика:
фэнтези
попаданцы
гаремник
5.00
рейтинг книги
Хозяин оков V

Петля, Кадетский корпус. Книга первая

Алексеев Евгений Артемович
1. Петля
Фантастика:
боевая фантастика
попаданцы
аниме
6.11
рейтинг книги
Петля, Кадетский корпус. Книга первая

Мое ускорение

Иванов Дмитрий
5. Девяностые
Фантастика:
попаданцы
альтернативная история
6.33
рейтинг книги
Мое ускорение

Кодекс Охотника. Книга XXXVIII

Винокуров Юрий
38. Кодекс Охотника
Фантастика:
фэнтези
боевая фантастика
попаданцы
юмористическое фэнтези
5.00
рейтинг книги
Кодекс Охотника. Книга XXXVIII

Истребители. Трилогия

Поселягин Владимир Геннадьевич
Фантастика:
альтернативная история
7.30
рейтинг книги
Истребители. Трилогия

Я царь. Книга XXVIII

Дрейк Сириус
28. Дорогой барон!
Фантастика:
боевая фантастика
аниме
попаданцы
5.00
рейтинг книги
Я царь. Книга XXVIII

Воплощение Похоти

Некрасов Игорь
1. Воплощение Похоти
Фантастика:
юмористическое фэнтези
попаданцы
рпг
аниме
5.00
рейтинг книги
Воплощение Похоти