Книга: 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 върху именувани и неименувани тръби
Отваряне на 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, тогава: