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

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

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

bsdi % udpcli01 192.168.42.255 < 2000line

sendto error: Message too long

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

Π­Ρ‚ΠΎ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ΠΎ Π² AIX, FreeBSD ΠΈ MacOS. Linux, Solaris ΠΈ HP-UX Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚ΠΈΡ€ΡƒΡŽΡ‚ Π΄Π΅ΠΉΡ‚Π°Π³Ρ€Π°ΠΌΠΌΡ‹, ΠΎΡ‚ΠΏΡ€Π°Π²Π»Π΅Π½Π½Ρ‹Π΅ Π½Π° ΡˆΠΈΡ€ΠΎΠΊΠΎΠ²Π΅Ρ‰Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ адрСс. Однако Π² цСлях пСрСносимости ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π½ΡƒΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ ΡˆΠΈΡ€ΠΎΠΊΠΎΠ²Π΅Ρ‰Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ запрос, Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ MTU для интСрфСйса, Ρ‡Π΅Ρ€Π΅Π· ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΡ‚ΠΏΡ€Π°Π²Π»Π΅Π½ΠΎ сообщСниС, ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π° SIOCGIPMTU Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ioctl, послС Ρ‡Π΅Π³ΠΎ Π²Ρ‹Ρ‡Π΅ΡΡ‚ΡŒ Ρ€Π°Π·ΠΌΠ΅Ρ€ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ² IP ΠΈ транспортного ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°. ΠΠ»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Π½Ρ‹ΠΉ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄: Π²Ρ‹Π±Ρ€Π°Ρ‚ΡŒ Ρ‚ΠΈΠΏΠΈΡ‡Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ MTU (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, 1500 для Ethernet) ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π΅Π³ΠΎ Π² качСствС константы.

20.5. Битуация Π³ΠΎΠ½ΠΎΠΊ

Битуация Π³ΠΎΠ½ΠΎΠΊ (race condition) ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚, ΠΊΠΎΠ³Π΄Π° мноТСство процСссов ΠΏΠΎΠ»ΡƒΡ‡Π°ΡŽΡ‚ доступ ΠΊ ΠΎΠ±Ρ‰ΠΈΠΌ для Π½ΠΈΡ… Π΄Π°Π½Π½Ρ‹ΠΌ, Π½ΠΎ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΡΡ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° зависит ΠΎΡ‚ порядка выполнСния процСссов. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ порядок выполнСния процСссов Π² Ρ‚ΠΈΠΏΠΈΡ‡Π½Ρ‹Ρ… систСмах Unix зависит ΠΎΡ‚ мноТСства Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΎΠ², ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΎΠ³ΡƒΡ‚ ΠΌΠ΅Π½ΡΡ‚ΡŒΡΡ ΠΎΡ‚ запуска ΠΊ запуску, ΠΈΠ½ΠΎΠ³Π΄Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π΅Π½, Π° ΠΈΠ½ΠΎΠ³Π΄Π° β€” Π½Π΅Ρ‚. НаиболСС слоТным для ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ Ρ‚ΠΈΠΏΠΎΠΌ Π³ΠΎΠ½ΠΎΠΊ являСтся Ρ‚Π°ΠΊΠΎΠΉ, ΠΊΠΎΠ³Π΄Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ получаСтся Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Ρ‹ΠΌ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΈΠ·Ρ€Π΅Π΄ΠΊΠ°. Π‘ΠΎΠ»Π΅Π΅ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ ΠΎ ситуациях Π³ΠΎΠ½ΠΎΠΊ ΠΌΡ‹ ΠΏΠΎΠ³ΠΎΠ²ΠΎΡ€ΠΈΠΌ Π² Π³Π»Π°Π²Π΅ 26, ΠΊΠΎΠ³Π΄Π° Π±ΡƒΠ΄Π΅ΠΌ ΠΎΠ±ΡΡƒΠΆΠ΄Π°Ρ‚ΡŒ Π²Π·Π°ΠΈΠΌΠ½Ρ‹Π΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ (mutex) ΠΈ условныС ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ (condition variables). ΠŸΡ€ΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² всСгда Π²ΠΎΠ·Π½ΠΈΠΊΠ°ΡŽΡ‚ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ с ситуациями Π³ΠΎΠ½ΠΎΠΊ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ΅ количСство Π΄Π°Π½Π½Ρ‹Ρ… являСтся ΠΎΠ±Ρ‰ΠΈΠΌ для всСх ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, всС Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹Π΅ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅).

Π‘ΠΈΡ‚ΡƒΠ°Ρ†ΠΈΠΈ Π³ΠΎΠ½ΠΎΠΊ Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° часто Π²ΠΎΠ·Π½ΠΈΠΊΠ°ΡŽΡ‚ ΠΏΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ с сигналами. ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ Π²ΠΎΠ·Π½ΠΈΠΊΠ°ΡŽΡ‚, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ сигнал, ΠΊΠ°ΠΊ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ, ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ доставлСн Π² любой ΠΌΠΎΠΌΠ΅Π½Ρ‚ Π²ΠΎ врСмя выполнСния нашСй ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹. POSIX позволяСт Π½Π°ΠΌ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ доставку сигнала, Π½ΠΎ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π° это часто Π½Π΅ Π΄Π°Π΅Ρ‚ эффСкта.

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ½ΡΡ‚ΡŒ эту ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ, рассмотрим ΠΏΡ€ΠΈΠΌΠ΅Ρ€. Битуация Π³ΠΎΠ½ΠΎΠΊ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΈΠ· листинга 20.1. ΠŸΠΎΡ‚Ρ€Π°Ρ‚ΡŒΡ‚Π΅ нСсколько ΠΌΠΈΠ½ΡƒΡ‚ ΠΈ посмотритС, смоТСтС Π»ΠΈ Π²Ρ‹ Π΅Π΅ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΡ‚ΡŒ. (Подсказка: Π² ΠΊΠ°ΠΊΠΎΠΌ мСстС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π½Π°Ρ…ΠΎΠ΄ΠΈΡ‚ΡŒΡΡ, ΠΊΠΎΠ³Π΄Π° доставляСтся сигнал?) Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Ρ‚Π°ΠΊΠΆΠ΅ ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΡΠΈΡ‚ΡƒΠ°Ρ†ΠΈΡŽ Π³ΠΎΠ½ΠΎΠΊ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ: ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ alarm с 5 Π½Π° 1 ΠΈ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π²Ρ‹Π·ΠΎΠ² sleep(1) сразу ΠΆΠ΅ послС printf.

Когда ΠΌΡ‹ послС внСсСния этих ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ Π½Π°Π±Π΅Ρ€Π΅ΠΌ ΠΏΠ΅Ρ€Π²ΡƒΡŽ строку Π²Π²ΠΎΠ΄Π°, эта строка Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΡ‚ΠΏΡ€Π°Π²Π»Π΅Π½Π° ΠΊΠ°ΠΊ ΡˆΠΈΡ€ΠΎΠΊΠΎΠ²Π΅Ρ‰Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΠ΅ сообщСниС, Π° ΠΌΡ‹ установим Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ alarm Ρ€Π°Π²Π½Ρ‹ΠΌ 1 с. ΠœΡ‹ блокируСмся Π² Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ recvfrom, Π° Π·Π°Ρ‚Π΅ΠΌ для нашСго сокСта ΠΏΡ€ΠΈΡ…ΠΎΠ΄ΠΈΡ‚ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΎΡ‚Π²Π΅Ρ‚, вСроятно, Π² Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠ΅ Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… миллисСкунд. ΠžΡ‚Π²Π΅Ρ‚ возвращаСтся Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ recvfrom, Π½ΠΎ Π·Π°Ρ‚Π΅ΠΌ ΠΌΡ‹ Π²Ρ…ΠΎΠ΄ΠΈΠΌ Π² спящСС состояниС Π½Π° ΠΎΠ΄Π½Ρƒ сСкунду. ΠŸΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‚ΡΡ ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅ ΠΎΡ‚Π²Π΅Ρ‚Ρ‹ ΠΈ ΠΏΠΎΠΌΠ΅Ρ‰Π°ΡŽΡ‚ΡΡ Π² ΠΏΡ€ΠΈΠ΅ΠΌΠ½Ρ‹ΠΉ Π±ΡƒΡ„Π΅Ρ€ сокСта. Но ΠΏΠΎΠΊΠ° ΠΌΡ‹ находимся Π² спящСм состоянии, врСмя Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π° alarm истСкаСт ΠΈ гСнСрируСтся сигнал SIGALRM. ΠŸΡ€ΠΈ этом вызываСтся наш ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ сигнала, Π·Π°Ρ‚Π΅ΠΌ ΠΎΠ½ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΈ ΠΏΡ€Π΅Ρ€Ρ‹Π²Π°Π΅Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ sleep, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ ΠΌΡ‹ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Ρ‹. Π”Π°Π»Π΅Π΅ ΠΌΡ‹ повторяСм Ρ†ΠΈΠΊΠ» ΠΈ Ρ‡ΠΈΡ‚Π°Π΅ΠΌ установлСнныС Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ ΠΎΡ‚Π²Π΅Ρ‚Ρ‹ с ΠΏΠ°ΡƒΠ·ΠΎΠΉ Π² ΠΎΠ΄Π½Ρƒ сСкунду ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π·, ΠΊΠΎΠ³Π΄Π° выводится ΠΎΡ‚Π²Π΅Ρ‚. ΠŸΡ€ΠΎΡ‡ΠΈΡ‚Π°Π² всС ΠΎΡ‚Π²Π΅Ρ‚Ρ‹, ΠΌΡ‹ снова блокируСмся Π² Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ recvfrom, ΠΎΠ΄Π½Π°ΠΊΠΎ Ρ‚Π°ΠΉΠΌΠ΅Ρ€ ΡƒΠΆΠ΅ Π½Π΅ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚. ΠœΡ‹ окаТСмся навсСгда Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Ρ‹ Π² Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ recvfrom. Π€ΡƒΠ½Π΄Π°ΠΌΠ΅Π½Ρ‚Π°Π»ΡŒΠ½Π°Ρ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° здСсь Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ наша Ρ†Π΅Π»ΡŒ β€” ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΡ‚ΡŒ ΠΏΡ€Π΅Ρ€Ρ‹Π²Π°Π½ΠΈΠ΅ блокирования Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ recvfrom ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠΌ сигнала, ΠΎΠ΄Π½Π°ΠΊΠΎ сигнал ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ доставлСн Π² любоС врСмя, ΠΈ наша ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ доставки сигнала ΠΌΠΎΠΆΠ΅Ρ‚ Π½Π°Ρ…ΠΎΠ΄ΠΈΡ‚ΡŒΡΡ Π² любом мСстС бСсконСчного Ρ†ΠΈΠΊΠ»Π° for.

Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΡ‹ ΠΏΡ€ΠΎΠ°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅ΠΌ Ρ‡Π΅Ρ‚Ρ‹Ρ€Π΅ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π° Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ этой ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹: ΠΎΠ΄Π½ΠΎ Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠ΅ ΠΈ Ρ‚Ρ€ΠΈ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Ρ‹Ρ… Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ.

Π‘Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΈ Ρ€Π°Π·Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ сигнала

НашС ΠΏΠ΅Ρ€Π²ΠΎΠ΅ (Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠ΅) Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ сниТаСт Π²Π΅Ρ€ΠΎΡΡ‚Π½ΠΎΡΡ‚ΡŒ появлСния ошибки, блокируя сигнал ΠΈ прСдотвращая Π΅Π³ΠΎ доставку, ΠΏΠΎΠΊΠ° наша ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° выполняСт ΠΎΡΡ‚Π°Π²ΡˆΡƒΡŽΡΡ Ρ‡Π°ΡΡ‚ΡŒ Ρ†ΠΈΠΊΠ»Π° for. Π­Ρ‚Π° вСрсия прСдставлСна Π² листингС 20.2.

Листинг 20.2. Π‘Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ сигналов ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Π² Ρ†ΠΈΠΊΠ»Π΅ for (Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠ΅ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅)

//bcast/dgclibcast3.c

 1 #include "unp.h"


 2 static void recvfrom_alarm(int);


 3 void

 4 dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)

 5 {

 6  int n;

 7  const int on = 1;

 8  char sendline[MAXLINE], recvline[MAXLINE + 1];

 9  sigset_t sigset_alrm;

10  socklen_t len;

11  struct sockaddr *preply_addr;


12  preply_addr = Malloc(servlen);


13  Setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));


14  Sigemptyset(&sigset_alrm);

15  Sigaddset(&sigset_alrm, SIGALRM);


16  Signal(SIGALRM, recvfrom_alarm);


17  while (Fgets(sendline, MAXLINE, fp) != NULL) {

18   Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);

19   alarm(5);

20   for (;;) {

21    len = servlen;

22    Sigprocmask(SIG_UNBLOCK, &sigset_alrm, NULL);

23    n = recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr, &len);

24    Sigprocmask(SIG_BLOCK, &sigset_alrm, NULL);

25    if (n < 0) {

26     if (errno == EINTR)

27      break; /* ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΠ΅ оТидания ΠΎΡ‚Π²Π΅Ρ‚Π° */

28     else

29      err_sys("recvfrom error");

30    } else {

31     recvline[n] = 0; /* Π·Π°Π²Π΅Ρ€ΡˆΠ°ΡŽΡ‰ΠΈΠΉ Π½ΡƒΠ»ΡŒ */

32     printf("from %s: %s",

33     Sock_ntop_host(preply_addr, len), recvline);

34    }

35   }

36  }

37  free(preply_addr);

38 }


39 static void

40 recvfrom_alarm(int signo)

41 {

42  return; /* Π²Ρ‹Ρ…ΠΎΠ΄ ΠΈΠ· recvfrom() */

43 }

ОбъявлСниС Π½Π°Π±ΠΎΡ€Π° сигналов ΠΈ инициализация

14-15 ΠœΡ‹ объявляСм Π½Π°Π±ΠΎΡ€ сигналов, ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅ΠΌ Π΅Π³ΠΎ ΠΊΠ°ΠΊ пустой Π½Π°Π±ΠΎΡ€ (sigemptyset) ΠΈ Π²ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌ Π±ΠΈΡ‚, ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ сигналу SIGALRM (sigaddset).

Π Π°Π·Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΈ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ сигнала

21-24 ΠŸΠ΅Ρ€Π΅Π΄ Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ recvfrom ΠΌΡ‹ Ρ€Π°Π·Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌ сигнал (с Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ½ ΠΌΠΎΠ³ Π±Ρ‹Ρ‚ΡŒ доставлСн, ΠΏΠΎΠΊΠ° наша ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Π°), Π° Π·Π°Ρ‚Π΅ΠΌ Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌ Π΅Π³ΠΎ, ΠΊΠ°ΠΊ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ функция recvfrom. Если сигнал гСнСрируСтся (истСкаСт врСмя Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π°), ΠΊΠΎΠ³Π΄Π° сигнал Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½, Ρ‚ΠΎ ядро Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅Ρ‚ этот Ρ„Π°ΠΊΡ‚, Π½ΠΎ Π΄ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ сигнал (Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ наш ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ) Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚, ΠΏΠΎΠΊΠ° сигнал Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π·Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½. Π’ этом состоит ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠΈΠ°Π»ΡŒΠ½Π°Ρ Ρ€Π°Π·Π½ΠΈΡ†Π° ΠΌΠ΅ΠΆΠ΄Ρƒ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠ΅ΠΉ сигнала ΠΈ Π΅Π³ΠΎ доставкой. Π’ Π³Π»Π°Π²Π΅ 10 [110] прСдоставлСна Π±ΠΎΠ»Π΅Π΅ подробная информация ΠΎΠ±ΠΎ всСх аспСктах ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ сигналов POSIX.

Если ΠΌΡ‹ ΠΎΡ‚ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€ΡƒΠ΅ΠΌ ΠΈ запустим эту ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ, Π½Π°ΠΌ Π±ΡƒΠ΄Π΅Ρ‚ ΠΊΠ°Π·Π°Ρ‚ΡŒΡΡ, Ρ‡Ρ‚ΠΎ ΠΎΠ½Π° Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Π½ΠΎΡ€ΠΌΠ°Π»ΡŒΠ½ΠΎ, Π½ΠΎ всС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, ΠΏΠΎΡ€ΠΎΠΆΠ΄Π°ΡŽΡ‰ΠΈΠ΅ ΡΠΈΡ‚ΡƒΠ°Ρ†ΠΈΡŽ Π³ΠΎΠ½ΠΎΠΊ, Π±ΠΎΠ»ΡŒΡˆΡƒΡŽ Ρ‡Π°ΡΡ‚ΡŒ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ Π±Π΅Π· ΠΊΠ°ΠΊΠΈΡ…-Π»ΠΈΠ±ΠΎ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ! ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° остаСтся: Ρ€Π°Π·Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ сигнала, Π²Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ recvfrom ΠΈ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ сигнала β€” всС эти дСйствия ΡΠ²Π»ΡΡŽΡ‚ΡΡ нСзависимыми систСмными Π²Ρ‹Π·ΠΎΠ²Π°ΠΌΠΈ. Π‘ΡƒΠ΄Π΅ΠΌ ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ функция recvfrom Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ послСдний ΠΎΡ‚Π²Π΅Ρ‚ Π½Π° Π½Π°ΡˆΡƒ Π΄Π΅ΠΉΡ‚Π°Π³Ρ€Π°ΠΌΠΌΡƒ, Π° сигнал доставляСтся ΠΌΠ΅ΠΆΠ΄Ρƒ Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ recvfrom ΠΈ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ сигнала. Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ Π²Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ recvfrom заблокируСтся навсСгда. ΠœΡ‹ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡ΠΈΠ»ΠΈ Ρ€Π°Π·ΠΌΠ΅Ρ€ ΠΎΠΊΠ½Π°, Π½ΠΎ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° ΠΎΡΡ‚Π°Π»Π°ΡΡŒ.

Π’Π°Ρ€ΠΈΠ°Π½Ρ‚ΠΎΠΌ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ установка глобального Ρ„Π»Π°Π³Π° ΠΏΡ€ΠΈ доставкС сигнала Π΅Π³ΠΎ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠΌ:

recvfrom_alarm(int signo) {

 had_alarm = 1;

 return;

}

Π€Π»Π°Π³ сбрасываСтся Π² 0 ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π·, ΠΊΠΎΠ³Π΄Π° вызываСтся функция alarm. Наша функция dg_cli провСряСт этот Ρ„Π»Π°Π³ ΠΏΠ΅Ρ€Π΅Π΄ Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ recvfrom ΠΈ Π½Π΅ Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ Π΅Π΅, Ссли Ρ„Π»Π°Π³ Π½Π΅Π½ΡƒΠ»Π΅Π²ΠΎΠΉ.

for (;;) {

 len = servlen;

 Sigprocmask(SIG_UNBLOCK, &sigset_alrm, NULL);

 if (had_alarm == 1)

  break;

 n = recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr, &len);

Если сигнал Π±Ρ‹Π» сгСнСрирован Π²ΠΎ врСмя Π΅Π³ΠΎ блокирования (послС ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅Π³ΠΎ возвращСния ΠΈΠ· Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ recvfrom), Ρ‚ΠΎ послС разблокирования Π² этой части ΠΊΠΎΠ΄Π° ΠΎΠ½ Π±ΡƒΠ΄Π΅Ρ‚ доставлСн ΠΏΠ΅Ρ€Π΅Π΄ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠ΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ sigprocmask, ΡƒΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°ΡŽΡ‰Π΅ΠΉ наш Ρ„Π»Π°Π³. Однако ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΎΠΉ Ρ„Π»Π°Π³Π° ΠΈ Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ recvfrom сущСствуСт ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΠΊ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ, Π² Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠ΅ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ сигнал ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ сгСнСрирован ΠΈ доставлСн, ΠΈ Ссли это ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ‚, Π²Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ recvfrom заблокируСтся навсСгда (разумССтся, ΠΌΡ‹ считаСм ΠΏΡ€ΠΈ этом, Ρ‡Ρ‚ΠΎ Π½Π΅ ΠΏΡ€ΠΈΡ…ΠΎΠ΄ΠΈΡ‚ Π½ΠΈΠΊΠ°ΠΊΠΈΡ… Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… ΠΎΡ‚Π²Π΅Ρ‚ΠΎΠ²).

Π‘Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΈ Ρ€Π°Π·Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ сигнала с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ pselect

Одним ΠΈΠ· ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Ρ‹Ρ… Ρ€Π΅ΡˆΠ΅Π½ΠΈΠΉ Π±ΡƒΠ΄Π΅Ρ‚ использованиС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ pselect (см. Ρ€Π°Π·Π΄Π΅Π» 6.9), ΠΊΠ°ΠΊ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π² листингС 20.3.

Листинг 20.3. Π‘Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΈ Ρ€Π°Π·Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ сигналов с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ pselect

//bcast/dgclibcast4.с

 1 #include "unp.h"


 2 static void recvfrom_alarm(int);