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

ЖАНРЫ

UNIX: взаимодействие процессов

Стивенс Уильям Ричард

Шрифт:

34 printf("microseconds: %.0f usec\n", Stop_time);

35 if (shared.counter != nloop * nthreads)

36 printf("error: counter = %ld\n", shared.counter);

37 Sem_unlink(Px_ipc_name(NAME));

38 exit(0);

39 }

Семафоры System V

Функция main программы, измеряющей быстродействие семафоров System V, приведена в листинге А.27, а функция incr показана в листинге А.28.

Листинг
А.27. Функция main для измерения быстродействия семафоров System V

//bench/incr_svsem1.c

1 #include "unpipc.h"

2 #define MAXNTHREADS 100

3 int nloop;

4 struct {

5 int semid;

6 long counter;

7 } shared;

8 struct sembuf postop, waitop;

9 void *incr(void *);

10 int

11 main(int argc, char **argv)

12 {

13 int i, nthreads;

14 pthread_t tid[MAXNTHREADS];

15 union semun arg;

16 if (argc != 3)

17 err_quit("usage: incr_svseml <#loops> <#threads>");

18 nloop = atoi(argv[1]);

19 nthreads = min(atoi(argv[2]), MAXNTHREADS);

20 /* создание семафора и инициализация его значением 0 */

21 shared.semid = Semget(IPC_PRIVATE, 1, IPC_CREAT | SVSEM_MODE);

22 arg.val =0;

23 Semctl(shared.semid, 0, SETVAL, arg);

24 postop.sem_num = 0; /* инициализация двух структур semop */

25 postop.sem_op = 1;

26 postop.sem_flg = 0;

27 waitop.sem_num = 0;

28 waitop.sem_op = –1;

29 waitop.sem_flg = 0;

30 /* создание всех потоков */

31 Set_concurrency(nthreads);

32 for (i = 0; i < nthreads; i++) {

33 Pthread_create(&tid[i], NULL, incr, NULL);

34 }

35 /* запуск таймера и разблокирование семафора */

36 Start_time;

37 Semop(shared.semid, &postop, 1); /* up by 1 */

38 /* ожидание завершения всех потоков */

39 for (i = 0; i < nthreads; i++) {

40 Pthread_join(tid[i], NULL);

41 }

42 printf("microseconds: %.0f usec\n", Stop_time);

43 if (shared.counter != nloop * nthreads)

44 printf("error: counter = %ld\n", shared, counter);

45 Semctl(shared.semid, 0, IPC_RMID);

46 exit(0);

47 }

Листинг
А.28. Увеличение общего счетчика с использованием семафоров System V

//bench/incr_svsem1.c

48 void *

49 incr(void *arg)

50 {

51 int i;

52 for (i = 0; i < nloop; i++) {

53 Semop(shared.semid, &waitop, 1);

54 shared.counter++;

55 Semop(shared.semid, &postop, 1);

56 }

57 return(NULL);

58 }

20-23 Создается семафор с одним элементом, значение которого инициализируется нулем.

24-29 Инициализируются две структуры semop: одна для увеличения семафора, а другая для ожидания его изменения. Обратите внимание, что поле sem_flg в обеих структурах имеет значение 0: флаг SEM_UNDO не установлен.

Семафоры System V с флагом SEM_UNDO

Единственное отличие от пpoгрaммы из листинга А.27 заключается в том, что поле sem_flg структур semop устанавливается равным SEM_UNDO, а не 0. Мы не приводим в книге новый листинг с этим небольшим изменением.

Блокировка записей fcntl

Последняя пpoгрaммa использует fcntl для синхронизации. Функция main приведена в листинге А.30. Эта программа будет выполняться успешно только в том случае, если количество потоков равно 1, поскольку блокировка fcntl предназначена для использования между процессами, а не между потоками одного процесса. При указании нескольких потоков каждый из них всегда имеет возможность получить блокировку (то есть вызовы writew_lock не приводят к остановке потока, потому что процесс уже является владельцем блокировки), и конечное значение счетчика оказывается неправильным.

Функция incr, использующая блокировку записей, приведена в листинге А.29.

Листинг А.29. Увеличение общего счетчика с использованием блокировки записей fcntl

//bench/incr_fcntl1.e

44 void *

45 incr(void *arg)

46 {

47 int i;

48 for (i = 0; i < nloop; i++) {

49 Writew_lock(shared.fd, 0, SEEK_SET, 0);

50 shared.counter++;

51 Un_lock(shared.fd, 0, SEEK_SET, 0);

52 }

53 return(NULL);

54 }

Листинг А.30. Функция main для измерения производительности блокировки fcntl

//bench/incr_fcntl1.e

4 #include "unpipc.h"

5 #define MAXNTHREADS 100

6 int nloop;

7 struct {

8 int fd;

9 long counter;

Поделиться с друзьями: