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

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«UNIX: Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° сСтСвых ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉΒ». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 231

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

НСкоторыС ядра Unix снабТСны Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ, которая Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚ ΠΈΠ· состояния оТидания Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄ΠΈΠ½ процСсс для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΎΠ΄Π½ΠΎΠ³ΠΎ клиСнтского запроса [107]. Π§Π°Ρ‰Π΅ всСго ΠΎΠ½Π° называСтся wakeup_one.

РаспрСдСлСниС клиСнтских соСдинСний ΠΌΠ΅ΠΆΠ΄Ρƒ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΌΠΈ процСссами

Π‘Π»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ Ρ‚Π΅ΠΌΠΎΠΉ обсуТдСния являСтся распрСдСлСниС клиСнтских соСдинСний ΠΌΠ΅ΠΆΠ΄Ρƒ свободными Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΌΠΈ процСссами, Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΌΠΈ Π² Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ accept. Для получСния этой ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΌΡ‹ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΡ†ΠΈΡ€ΡƒΠ΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ main, размСщая Π² совмСстно ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΠΎΠΉ области памяти массив счСтчиков, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡŽΡ‚ собой Π΄Π»ΠΈΠ½Π½Ρ‹Π΅ Ρ†Π΅Π»Ρ‹Π΅ числа (ΠΎΠ΄ΠΈΠ½ счСтчик Π½Π° ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΉ процСсс). Π­Ρ‚ΠΎ дСлаСтся ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

long *cptr, *meter(int); /* для подсчСта количСства ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠ² Π½Π° ΠΎΠ΄ΠΈΠ½

Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΉ процСсс */

cptr = meter(nchildren); /* ΠΏΠ΅Ρ€Π΅Π΄ ΠΏΠΎΡ€ΠΎΠΆΠ΄Π΅Π½ΠΈΠ΅ΠΌ Π΄ΠΎΡ‡Π΅Ρ€Π½Π΅Π³ΠΎ процСсса */

Π’ листингС 30.10 ΠΏΠΎΠΊΠ°Π·Π°Π½Π° функция meter.

Листинг 30.10. Ѐункция meter, которая Ρ€Π°Π·ΠΌΠ΅Ρ‰Π°Π΅Ρ‚ массив Π² совмСстно ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΠΎΠΉ памяти

//server/meter.c

 1 #include "unp.h"

 2 #include <sys/mman.h>


 3 /* Π Π°Π·ΠΌΠ΅Ρ‰Π°Π΅ΠΌ массив "nchildren" Π΄Π»ΠΈΠ½Π½Ρ‹Ρ… Ρ†Π΅Π»Ρ‹Ρ… чисСл

 4  * Π² совмСстно ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΠΎΠΉ области памяти.

 5  * Π­Ρ‚ΠΈ числа ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ счСтчики количСства

    * ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠ², обслуТСнных Π΄Π°Π½Π½Ρ‹ΠΌ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΌ процСссом,

 6  * см. с. 467-470 ΠΊΠ½ΠΈΠ³ΠΈ [110]"

 7  */


 8 long*

 9 meter(int nchildren)

10 {

11  int fd;

12  long *ptr;


13 #ifdef MAP_ANON

14  ptr = Mmap(0, nchildren * sizeof(long), PROT_READ | PROT_WRITE,

15   MAP_ANON | MAP_SHARED, -1, 0);

16 #else

17  fd = Open("/dev/zero", O_RDWR, 0);


18  ptr = Mmap(0, nchildren * sizeof(long), PROT_READ | PROT_WRITE,

19   MAP_SHARED, fd, 0);

20  Close(fd);

21 #endif


22  return (ptr);

23 }

ΠœΡ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Π½Π΅ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π² ΠΏΠ°ΠΌΡΡ‚ΡŒ, Ссли ΠΎΠ½ΠΎ поддСрТиваСтся (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π² 4.4BSD), ΠΈΠ»ΠΈ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Ρ„Π°ΠΉΠ»Π° /dev/zero (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, SVR4). ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ массив создаСтся Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ mmap Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ процСсс ΠΏΠΎΡ€ΠΎΠΆΠ΄Π°Π΅Ρ‚ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠ΅, этот массив Π·Π°Ρ‚Π΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ совмСстно Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΈΠΌ ΠΈ всСми Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΌΠΈ процСссами, созданными Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ fork.

Π—Π°Ρ‚Π΅ΠΌ ΠΌΡ‹ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΡ†ΠΈΡ€ΡƒΠ΅ΠΌ Π½Π°ΡˆΡƒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ child_main (см. листинг 30.9) Ρ‚Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΉ процСсс ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π» Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π³ΠΎ счСтчика Π½Π° Π΅Π΄ΠΈΠ½ΠΈΡ†Ρƒ ΠΏΡ€ΠΈ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ accept, Π° послС Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ выполнСния всСх Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΡ… процСссов ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ сигнала SIGINT Π²Ρ‹Π²ΠΎΠ΄ΠΈΠ» Π±Ρ‹ упомянутый массив счСтчиков.

Π’ Ρ‚Π°Π±Π». 30.2 ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ распрСдСлСниС Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ ΠΏΠΎ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠΌ процСссам. Когда свободныС Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠ΅ процСссы Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Ρ‹ Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ accept, ΠΈΠΌΠ΅ΡŽΡ‰ΠΈΠΉΡΡ Π² ядрС Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌ планирования Ρ€Π°Π²Π½ΠΎΠΌΠ΅Ρ€Π½ΠΎ распрСдСляСт Π½Π°Π³Ρ€ΡƒΠ·ΠΊΡƒ, Ρ‚Π°ΠΊ Ρ‡Ρ‚ΠΎ Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ всС Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠ΅ процСссы ΠΎΠ±ΡΠ»ΡƒΠΆΠΈΠ²Π°ΡŽΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎΠ΅ количСство клиСнтских запросов.

Коллизии ΠΏΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ select

Рассматривая Π΄Π°Π½Π½Ρ‹ΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π² 4.4BSD, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΈΡΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚ΡŒ Π΅Ρ‰Π΅ ΠΎΠ΄Π½Ρƒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ, которая встрСчаСтся довольно Ρ€Π΅Π΄ΠΊΠΎ ΠΈ поэтому часто остаСтся нСпонятой Π΄ΠΎ ΠΊΠΎΠ½Ρ†Π°. Π’ Ρ€Π°Π·Π΄Π΅Π»Π΅ 16.13 [128] говорится ΠΎ коллизиях (collisions), Π²ΠΎΠ·Π½ΠΈΠΊΠ°ΡŽΡ‰ΠΈΡ… ΠΏΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ select нСсколькими процСссами Π½Π° ΠΎΠ΄Π½ΠΎΠΌ ΠΈ Ρ‚ΠΎΠΌ ΠΆΠ΅ дСскрипторС, ΠΈ ΠΎ Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ ядро Ρ€Π΅ΡˆΠ°Π΅Ρ‚ эту ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ. Π‘ΡƒΡ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π² структурС socket прСдусмотрСно мСсто Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π° процСсса, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ выводится ΠΈΠ· состояния оТидания ΠΏΠΎ готовности дСскриптора. Если ΠΆΠ΅ имССтся нСсколько процСссов, ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‰ΠΈΡ…, ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅Ρ‚ Π³ΠΎΡ‚ΠΎΠ² Π΄Π°Π½Π½Ρ‹ΠΉ дСскриптор, Ρ‚ΠΎ ядро Π΄ΠΎΠ»ΠΆΠ½ΠΎ вывСсти ΠΈΠ· состояния оТидания всС процСссы, Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ Π² Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ select, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ядро Π½Π΅ Π·Π½Π°Π΅Ρ‚, ΠΊΠ°ΠΊΠΈΠ΅ ΠΈΠΌΠ΅Π½Π½ΠΎ процСссы ΠΎΠΆΠΈΠ΄Π°ΡŽΡ‚ готовности Π΄Π°Π½Π½ΠΎΠ³ΠΎ дСскриптора.

Коллизии ΠΏΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ select Π² нашСм ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΌΠΎΠΆΠ½ΠΎ Ρ„ΠΎΡ€ΡΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ, прСдваряя Π²Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ accept ΠΈΠ· листинга 30.9 Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ select Π² ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠΈ готовности ΠΊ Ρ‡Ρ‚Π΅Π½ΠΈΡŽ Π½Π° ΠΏΡ€ΠΎΡΠ»ΡƒΡˆΠΈΠ²Π°Π΅ΠΌΠΎΠΌ сокСтС. Π”ΠΎΡ‡Π΅Ρ€Π½ΠΈΠ΅ процСссы Π±ΡƒΠ΄ΡƒΡ‚ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Ρ‹ Π² Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ select, Π° Π½Π΅ Π² Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ accept. Π’ листингС 30.11 ΠΏΠΎΠΊΠ°Π·Π°Π½Π° измСняСмая Ρ‡Π°ΡΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ child_main, ΠΏΡ€ΠΈ этом ΠΈΠ·ΠΌΠ΅Π½Π΅Π½Π½Ρ‹Π΅ ΠΏΠΎ ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΡŽ ΠΊ листингу 30.9 строки ΠΎΡ‚ΠΌΠ΅Ρ‡Π΅Π½Ρ‹ Π·Π½Π°ΠΊΠ°ΠΌΠΈ +.

Листинг 30.11. ΠœΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΡ листинга 30.9: Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π² Π²Ρ‹Π·ΠΎΠ²Π΅ select вмСсто блокирования Π² Π²Ρ‹Π·ΠΎΠ²Π΅ accept

  printf("child %ld starting\n", (long)getpid());

+ FD_ZERO(&rset);

  for (;;) {

+  FD_SET(listenfd, &rset);

+  Select(listenfd+1, &rset, NULL, NULL, NULL);

+  if (FD_ISSET(listenfd, &rset) == 0)

+   err_quit("listenfd readable");

+

   clilen = addrlen;

   connfd = Accept(listenfd, cliaddr, &clilen);


   web_child(connfd); /* ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° запроса */

   Close(connfd);

  }

Если, ΠΏΡ€ΠΎΠ΄Π΅Π»Π°Π² это ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅, ΠΌΡ‹ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ счСтчика ядра BSD/OS nselcoll, ΠΌΡ‹ ΡƒΠ²ΠΈΠ΄ΠΈΠΌ, Ρ‡Ρ‚ΠΎ Π² ΠΏΠ΅Ρ€Π²ΠΎΠΌ случаС ΠΏΡ€ΠΈ запускС сСрвСра ΠΏΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»ΠΎ 1814 ΠΊΠΎΠ»Π»ΠΈΠ·ΠΈΠΉ, Π° Π²ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΌ случаС β€” 2045. Π’Π°ΠΊ ΠΊΠ°ΠΊ ΠΏΡ€ΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ запускС сСрвСра Π΄Π²Π° ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° ΡΠΎΠ·Π΄Π°ΡŽΡ‚ Π² суммС 5000 соСдинСний, ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Ρ‹Π΅ Π²Ρ‹ΡˆΠ΅ значСния ΡƒΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‚, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ Π² 35-40% случаСв Π²Ρ‹Π·ΠΎΠ²Ρ‹ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ select приводят ΠΊ коллизиям.

Если ΡΡ€Π°Π²Π½ΠΈΡ‚ΡŒ значСния Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ, Π·Π°Ρ‚Ρ€Π°Ρ‡Π΅Π½Π½ΠΎΠ³ΠΎ Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΡŒΠ½Ρ‹ΠΌ процСссором Π² этом ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅, Ρ‚ΠΎ получится, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠΈ Π²Ρ‹Π·ΠΎΠ²Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ select это Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ увСличиваСтся с 1,8 Π΄ΠΎ 2,9 с. Частично это ΠΎΠ±ΡŠΡΡΠ½ΡΠ΅Ρ‚ΡΡ, вСроятно, Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ΠΌ систСмного Π²Ρ‹Π·ΠΎΠ²Π° (Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΡ‹ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ accept, Π½ΠΎ Π΅Ρ‰Π΅ ΠΈ select), Π° частично β€” Π½Π°ΠΊΠ»Π°Π΄Π½Ρ‹ΠΌΠΈ расходами, связанными с коллизиями.

Из этого ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° слСдуСт Π²Ρ‹Π²ΠΎΠ΄, Ρ‡Ρ‚ΠΎ ΠΊΠΎΠ³Π΄Π° нСсколько процСссов Π±Π»ΠΎΠΊΠΈΡ€ΡƒΡŽΡ‚ΡΡ Π½Π° ΠΎΠ΄Π½ΠΎΠΌ ΠΈ Ρ‚ΠΎΠΌ ΠΆΠ΅ дСскрипторС, Π»ΡƒΡ‡ΡˆΠ΅, Ρ‡Ρ‚ΠΎΠ±Ρ‹ эта Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ° Π±Ρ‹Π»Π° связана с Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ accept, Π° Π½Π΅ с Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ select.

30.7. Π‘Π΅Ρ€Π²Π΅Ρ€ TCP с ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌ ΠΏΠΎΡ€ΠΎΠΆΠ΄Π΅Π½ΠΈΠ΅ΠΌ процСссов ΠΈ Π·Π°Ρ‰ΠΈΡ‚ΠΎΠΉ Π²Ρ‹Π·ΠΎΠ²Π° accept Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΎΠΉ Ρ„Π°ΠΉΠ»Π°

Описанная Π²Ρ‹ΡˆΠ΅ рСализация, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰Π°Ρ нСскольким процСссам Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ accept Π½Π° ΠΎΠ΄Π½ΠΎΠΌ ΠΈ Ρ‚ΠΎΠΌ ΠΆΠ΅ ΠΏΡ€ΠΎΡΠ»ΡƒΡˆΠΈΠ²Π°Π΅ΠΌΠΎΠΌ дСскрипторС, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Π° Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для систСм 4.4BSD, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… функция accept Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° Π²Π½ΡƒΡ‚Ρ€ΠΈ ядра. Π―Π΄Ρ€Π° систСмы SVR4, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… accept Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° ΠΊΠ°ΠΊ библиотСчная функция, Π½Π΅ Π΄ΠΎΠΏΡƒΡΠΊΠ°ΡŽΡ‚ этого. Π’ самом Π΄Π΅Π»Π΅, Ссли ΠΌΡ‹ запустим сСрвСр ΠΈΠ· ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅Π³ΠΎ Ρ€Π°Π·Π΄Π΅Π»Π°, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ имССтся нСсколько Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΡ… процСссов, Π² Solaris 2.5 (систСма SVR4), Ρ‚ΠΎ вскорС послС Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Ρ‹ Π½Π°Ρ‡Π½ΡƒΡ‚ ΡΠΎΠ΅Π΄ΠΈΠ½ΡΡ‚ΡŒΡΡ с сСрвСром, Π²Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ accept Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΈΠ· Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΡ… процСссов Π²Ρ‹Π·ΠΎΠ²Π΅Ρ‚ ΠΎΡˆΠΈΠ±ΠΊΡƒ EPROTO, Ρ‡Ρ‚ΠΎ ΡΠ²ΠΈΠ΄Π΅Ρ‚Π΅Π»ΡŒΡΡ‚Π²ΡƒΠ΅Ρ‚ ΠΎΠ± ошибкС ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°.

ΠŸΠ Π˜ΠœΠ•Π§ΠΠΠ˜Π•

ΠŸΡ€ΠΈΡ‡ΠΈΠ½Ρ‹ возникновСния этой ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ с Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅Ρ‡Π½ΠΎΠΉ вСрсиСй Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ accept Π² SVR4 связаны с Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² STREAMS ΠΈ Ρ‚Π΅ΠΌ Ρ„Π°ΠΊΡ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ библиотСчная функция accept Π½Π΅ являСтся Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠ΅ΠΉ. Π’ Solaris 2.6 эта ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Ρ€Π΅ΡˆΠ΅Π½Π°, Π½ΠΎ Π² Π±ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²Π΅ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΉ SVR4 ΠΎΠ½Π° остаСтся.

РСшСниСм этой ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ являСтся Π·Π°Ρ‰ΠΈΡ‚Π° Π²Ρ‹Π·ΠΎΠ²Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ accept ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ, Ρ‚Π°ΠΊ Ρ‡Ρ‚ΠΎ Π² Π΄Π°Π½Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄ΠΈΠ½ процСсс ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ Π² Π²Ρ‹Π·ΠΎΠ²Π΅ этой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. Π”Ρ€ΡƒΠ³ΠΈΠ΅ процСссы Ρ‚Π°ΠΊΠΆΠ΅ Π±ΡƒΠ΄ΡƒΡ‚ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Ρ‹, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΎΠ½ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ ΡΡ‚Ρ€Π΅ΠΌΠΈΡ‚ΡŒΡΡ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΡƒ для Π²Ρ‹Π·ΠΎΠ²Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ accept.

БущСствуСт нСсколько способов Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π·Π°Ρ‰ΠΈΡ‚Ρ‹ Π²Ρ‹Π·ΠΎΠ²Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ accept, ΠΎ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… рассказываСтся Π²ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΌ Ρ‚ΠΎΠΌΠ΅[2] Π΄Π°Π½Π½ΠΎΠΉ сСрии. Π’ этом Ρ€Π°Π·Π΄Π΅Π»Π΅ ΠΌΡ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΡƒ Ρ„Π°ΠΉΠ»Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ fcntl согласно стандарту POSIX.

ЕдинствСнным ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ΠΌ Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ main (см. листинг 30.6) Π±ΡƒΠ΄Π΅Ρ‚ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π²Ρ‹Π·ΠΎΠ²Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ my_lock_init ΠΏΠ΅Ρ€Π΅Π΄ Π½Π°Ρ‡Π°Π»ΠΎΠΌ Ρ†ΠΈΠΊΠ»Π°, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΡΠΎΠ·Π΄Π°ΡŽΡ‚ΡΡ Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΠ΅ процСссы:

+ my_lock_init("/tmp/lock.XXXXXX"); /* ΠΎΠ΄ΠΈΠ½ Ρ„Π°ΠΉΠ» для всСх Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΡ…

                                       процСссов */

  for (i = 0; i < nchildren; i++)

   pids[i] = child_make(i, listenfd, addrlen); /* Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅

                                       Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ процСсса */

Ѐункция child_make остаСтся Ρ‚Π°ΠΊΠΎΠΉ ΠΆΠ΅, ΠΊΠ°ΠΊ Π² листингС 30.8. ЕдинствСнным ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ child_main (см. листинг 30.9) являСтся Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π΅Π΄ Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ accept ΠΈ снятиС Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ послС Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ этой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ:

  for (;;) {

   clilen = addrlen;

+  my_lock_wait();

    connfd = Accept(listenfd, cliaddr, &clilen);

+   my_lock_release();


    web_child(connfd); /* ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° запроса */

    Close(connfd);

   }

Π’ листингС 30.12 ΠΏΠΎΠΊΠ°Π·Π°Π½Π° наша функция my_lock_init, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ° Ρ„Π°ΠΉΠ»Π° согласно стандарту POSIX.

Листинг 30.12. Ѐункция my_lock_init: Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ° Ρ„Π°ΠΉΠ»Π°

//server/lock_fcntl.c

 1 #include "unp.h"


 2 static struct flock lock_it, unlock_it;

 3 static int lock_fd = -1;