Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«UNIX: взаимодСйствиС процСссов». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 119

Автор Уильям БтивСнс

45   Sem_wait(shared.mutex);

46   shared.counter++;

47   Sem_post(shared.mutex);

48  }

49  return(NULL);

50 }

Листинг А.26. Ѐункция main для измСрСния быстродСйствия ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½Π½Ρ‹Ρ… сСмафоров Posix

//bench/incr_pxsem2.с

1  #include "unpipc.h"

2  #define MAXNTHREADS 100

3  #define NAME "incr_pxsem2"


4  int nloop;

5  struct {

6   sem_t *mutex; /* ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ сСмафор */

7   long counter;

8  } shared;

9  void *incr(void *);


10 int

11 main(int argc, char **argv)

12 {

13  int i, nthreads;

14  pthread_t tid[MAXNTHREADS];

15  if (argc != 3)

16   err_quit("usage: incr_pxsem2 <#loops> <#threads>");

17  nloop = atoi(argv[1]);

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

19  /* инициализация ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ сСмафора 0 */

20  sem_unlink(Px_ipc_name(NAME)); /* ошибка – OK */

21  shared.mutex = Sem_open(Px_ipc_name(NAME), O_CREAT | O_EXCL, FILE_MODE, 0);

22  /* созданиС всСх ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² */

23  Set_concurrency(nthreads);

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

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

26  }

27  /* запуск Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π° ΠΈ Ρ€Π°Π·Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ сСмафора */

28  Start_time();

29  Sem_post(shared.mutex);

30  /* ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ всСх ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² */

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

32   Pthread_join(tid[i], NULL);

33  }

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;

10 } shared;

11 void *incr(void *);


12 int

13 main(int argc, char **argv)

14 {

15  int i, nthreads;

16  char *pathname;

17  pthread_t tid[MAXNTHREADS];

18  if (argc != 4)

19   err_quit("usage: incr_fcntll <pathname> <#loops> <#threads>");

20  pathname = argv[1];

21  nloop = atoi(argv[2]);

22  nthreads = min(atoi(argv[3]), MAXNTHREADS);

23  /* созданиС Ρ„Π°ΠΉΠ»Π° ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ Π½Π° запись */

24  shared.fd = Open(pathname, O_RDWR | O_CREAT | O_TRUNC, FILE_MODE);

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

26  /* созданиС всСх ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² */

27  Set_concurrency(nthreads);

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

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

30  }

31  /* запуск Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π° ΠΈ снятиС Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ Π½Π° запись */

32  Start_time();

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

34  /* ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ всСх ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² */

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

36   Pthread_join(tid[i], NULL);

37  }

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

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

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

41  Unlink(pathname);

42  exit(0);

43 }

15-19 ПолноС имя создаваСмого ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΠΎΠ³ΠΎ для Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ Ρ„Π°ΠΉΠ»Π° принимаСтся Π² качСствС Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π° ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строки. Π­Ρ‚ΠΎ позволяСт ΠΈΠ·ΠΌΠ΅Ρ€ΡΡ‚ΡŒ ΡΠΊΠΎΡ€ΠΎΡΡ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Ρ‹ для Ρ€Π°Π·Π½Ρ‹Ρ… Ρ„Π°ΠΉΠ»ΠΎΠ²Ρ‹Ρ… систСм. МоТно ΠΎΠΆΠΈΠ΄Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π³ΠΎΡ€Π°Π·Π΄ΠΎ ΠΌΠ΅Π΄Π»Π΅Π½Π½Π΅Π΅ ΠΏΡ€ΠΈ использовании NFS (Ссли ΠΎΠ½Π° Π²ΠΎΠΎΠ±Ρ‰Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ, Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ Ссли сСрвСр ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ NFS ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΡƒ записСй NFS).

А.6. Бинхронизация процСссов: ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹

Π’ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°Ρ… ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅Π³ΠΎ Ρ€Π°Π·Π΄Π΅Π»Π° счСтчик использовался нСсколькими ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ ΠΎΠ΄Π½ΠΎΠ³ΠΎ процСсса. ΠŸΡ€ΠΈ этом ΠΎΠ½ прСдставлял собой Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½ΡƒΡŽ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ. Π’Π΅ΠΏΠ΅Ρ€ΡŒ Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ эти ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ для измСрСния скорости синхронизации Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… процСссов.

Для раздСлСния счСтчика ΠΌΠ΅ΠΆΠ΄Ρƒ Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΈΠΌ процСссом ΠΈ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΌΠΈ ΠΌΡ‹ ΠΏΠΎΠΌΠ΅Ρ‰Π°Π΅ΠΌ Π΅Π³ΠΎ Π² Ρ€Π°Π·Π΄Π΅Π»ΡΠ΅ΠΌΡƒΡŽ ΠΏΠ°ΠΌΡΡ‚ΡŒ, Π²Ρ‹Π΄Π΅Π»ΡΠ΅ΠΌΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ my_shm, ΠΏΠΎΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ Π² листингС А.31.

Листинг А.31. Π’Ρ‹Π΄Π΅Π»Π΅Π½ΠΈΠ΅ раздСляСмой памяти ΠΏΠΎΠ΄ Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ ΠΈ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠ΅ процСссы

//lib/my_shm.c

1  #include "unpipc.h"


2  void *

3  my_shm(size_t nbytes)

4  {

5   void *shared;

6  #if defined(MAP_ANON)

7   shared = mmap(NULL, nbytes, PROT_READ | PROT_WRITE,

8   MAP_ANON | MAP_SHARED, –1, 0);

9  #elif defined(HAVE_DEV_ZERO)

10  int fd;

11  /* ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π² ΠΏΠ°ΠΌΡΡ‚ΡŒ Ρ„Π°ΠΉΠ»Π° /dev/zero */

12  if ((fd = open("/dev/zero", O_RDWR)) == –1)

13   return(MAP_FAILED);

14  shared = mmap(NULL, nbytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

15  close(fd);

16 #else

17 # error cannot determine what type of anonymous shared memory to use

18 #endif

19  return(shared); /* ошибка отобраТСния Π² ΠΏΠ°ΠΌΡΡ‚ΡŒ */

20 }

Если систСма ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ Ρ„Π»Π°Π³ MAP_ANON (Ρ€Π°Π·Π΄Π΅Π» 12.4), ΠΌΡ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ этот Ρ‚ΠΈΠΏ раздСляСмой памяти. Π’ ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π² ΠΏΠ°ΠΌΡΡ‚ΡŒ Ρ„Π°ΠΉΠ»Π° /dev/zero (Ρ€Π°Π·Π΄Π΅Π» 12.5).