Вход/Регистрация
UNIX: взаимодействие процессов
вернуться

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

Шрифт:

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++;

  • Читать дальше
  • 1
  • ...
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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