Книга: UNIX: Процесна комуникация

Книгата е написана от известен експерт по операционната система UNIX и е посветена на описанието на една от формите на междупроцесна комуникация, IPC, която се използва за създаване на най-сложни програми. Той описва четири възможности за разделяне на задачи между множество процеси или нишки на един и същи процес: предаване на съобщения, синхронизация, споделена памет и извикване на отдалечена процедура.

Книгата съдържа голям брой илюстративни примери и може да се използва както като учебник по IPC, така и като справочник за опитни програмисти.

Книга: UNIX: Процесна комуникация

4.7. Някои свойства на именувани и неименувани тръби

4.7. Някои свойства на именувани и неименувани тръби

Някои свойства на именувани и неименувани тръби, свързани с отварянето им и четенето и записването на данни, заслужават по-голямо внимание. Първо, можете да направите манипулатора неблокиращ по два начина.

1. Когато извиквате open, посочете флага O_NONBLOCK. Например, първото отворено повикване в листинг 4-9 може да изглежда така:

writefd = Open(FIFO1, O_WRONLY O_NONBLOCK, 0);

2. Ако манипулаторът вече е отворен, можете да използвате fcntl, за да включите флага O_NONBLOCK. Тази техника трябва да се използва за програмни канали, тъй като отворената функция не се извиква за тях и няма начин да се посочи флагът O_NONBLOCK, когато се извиква. Използвайки fcntl, първо получаваме текущия статус на файла с F_GETFL, след това добавяме флага O_NONBLOCK с побитово логическо добавяне (OR) към него и записваме новия статус с командата F_SETFL:

int флагове; ако ((флагове = fcntl(fd, F_GETFL, 0))

Бъдете внимателни с програми, които просто задават необходимия флаг, тъй като това ще нулира всички останализнамена за състояние:

/* Деактивиране на невалидно блокиране */ if (fcntl(fd, F_SETFL, O_NONBLOCK)

Таблица 4.1 илюстрира действието на флага за забрана, когато се отвори опашка и когато данните се четат от празен програмен канал или FIFO канал.

Таблица 4.1. Ефект на флага O_NONBLOCK върху именувани и неименувани тръби

Операция Наличие на отворени канали Блокирането е активирано (по подразбиране) Зададен флаг O_NONBLOCK
Отваряне на FIFO само за четенеFIFO отворен за писанеВръща се кодът за успех на операцията.Връща се кодът за успех на операцията.
Отваряне на FIFO само за четенеFIFO не е отворен за писанеПроцесът блокира, докато FIFO не бъде отворен за запис.Връща се кодът за успех на операцията.
Отваряне (отворено) FIFO само за записFIFO отворен за четенеВръща кода за успех на операциятаВръща кода за успех на операцията
Отваряне (отворено) FIFO само за записFIFO не е отворен за четенеБлокира, докато FIFO не бъде отворен за четене.Връща грешка с код ENXIO
Четене от празен програмен канал или FIFOПрограмен канал или FIFO отворен за записБлокира, докато данните не бъдат поставени в програмния канал или FIFO или не бъдат затворени от всички процеси, които са ги отворили за запис.Връща грешка с код EAGAIN
Четене от празен програмен канал или FIFOПрограмният канал или FIFO не са отворени за записчетенето връща 0 (край на файла)четенето връща 0 (край на файла)
Пишете на програмен канал или FIFOПрограмен канал или FIFO отворен за четене(Виж в текста)(Виж в текста)
Пишете на програмен канал или FIFOПрограмният канал или FIFO не са отворени за четенеСигналът SIGPIPE се изпраща към нишката на програмата.Сигналът SIGPIPE се изпраща към нишката на програмата.

Запомнете няколко допълнителни правила, които се прилагат при четене и запис на данни в програмни канали и FIFO.

? Ако се опитате да прочетете повече данни, отколкото се съдържат в момента в програмния канал или FIFO, се връща само наличното количество данни. Трябва да се обмисли справянето със ситуацията, в която функцията за четене връща по-малко данни, отколкото са били поискани.

? Ако броят на байтовете, записани във функцията за запис, не надвишава стойността на PIPE_BUF (ограничение, зададено от стандарта Posix, което се обсъжда по-подробно в раздел 4.11), тогава ядрото гарантираатомарностна операцията за запис. Това означава, че ако два процеса записват данни в програмния канал или FIFO приблизително по едно и също време, тогава всички данни от първия процес първо ще бъдат поставени в буфера, а след това от втория или обратно. Данните от двата процеса няма да се смесват. Въпреки това, ако броят на байтовете надвишава стойността на PIPEBUF, операцията за запис не е гарантирана, че е атомарна.

ЗАБЕЛЕЖКА

Posix.1 изисква стойността на PIPE_BUF да бъде поне 512. Типичните стойности, срещани на практика, варират от 1024 (BSD/OS 3.1) до 5120 байта (Solaris 2.6). Раздел 4.11 съдържа текста на програмата, която показва стойността на тази константа.

? Задаването на флага O_NONBLOCK не влияе върху атомарността на операцията за запис в програмния каналили FIFO - определя се единствено от количеството изпратени данни в сравнение със стойността на PIPE_BUF. Въпреки това, ако заключването е деактивирано за програмния канал или FIFO, върнатата стойност на запис зависи от броя байтове, изпратени за запис, и количеството свободно пространство в програмния канал или FIFO. Ако броят на байтовете не надвишава стойността PIPE_BUF, тогава:

? Ако в канала има достатъчно място за запис на необходимото количество данни, те ще бъдат прехвърлени всички наведнъж.

? Ако няма достатъчно място в програмния канал или FIFO за запис на необходимото количество данни, функцията прекратява незабавно с върната грешка EAGAIN. Тъй като флагът O_NONBLOCK е зададен, процесът не може да бъде блокиран, но в същото време ядрото не може да приеме само част от данните, тъй като не може да гарантира атомарността на операцията за запис. Така че ядрото връща грешка, казвайки на процеса да опита да запише отново.

? Ако броят на байтовете надвишава стойността на PIPE_BUF, тогава: