Что происходит, когда я пытаюсь читать из канала без записи в него? - PullRequest
0 голосов
/ 10 февраля 2019

С этой операцией я ожидал получить ошибку, потому что я читаю с нуля, но на самом деле программа, кажется, продолжает пытаться читать, пока кто-то не пишет в нее.Если записи нет, она застрянет в неопределенном цикле, пытаясь прочитать, и не будет продолжаться.

Что именно происходит за кулисами, продолжает ли функция повторяться, или она ожидает сигнала, иличто-то еще происходит?Он все еще потребляет ресурсы процессора?

Кроме того, можно ли заставить программу возвращать код ошибки / распечатывать что-либо при попытке чтения без каких-либо записей?Мне не нужно этого делать, просто интересно, возможно ли это.

1 Ответ

0 голосов
/ 11 февраля 2019

Это нормальное поведение.Если ничего не доступно для чтения, процесс чтения будет блокироваться, пока не будет.Это не будет потреблять процессорное время, блокируя;ОС переводит его в спящий режим до тех пор, пока другой процесс не запишет в канал.

Имейте в виду, что каналы были спроектированы как несколько прозрачные;простая программа типа фильтра не должна заботиться о том, является ли входной файл файлом или каналом.Если бы каждая программа, которая хотела иметь возможность читать из канала (думаю, grep), должна была включать специальную обработку для ожидания готовности писателя, это было бы очень утомительно для этих программистов.Такое поведение означает, что для чтения из каналов не требуется делать ничего особенного.

Если вы не хотите блокировать, если данные недоступны, вы можете установить флаг состояния O_NONBLOCK в дескрипторе файла, либокогда вы open(2) это или с fcntl(fd, F_SETFL, ...).В этом случае, когда данные недоступны, read(2) вернет -1 и установит errno в EAGAIN или EWOULDBLOCK.Это, конечно, означает, что каждый раз, когда вы читаете из файлового дескриптора, вы должны написать код для обработки такого случая.

Вы также можете использовать select(2) или poll(2), чтобы дождаться, пока данные станут доступны., опционально с тайм-аутом.

Также возможно организовать его так, чтобы сигнал, поступающий во время блокировки, заставил read(2) вернуть -1 и установить errno в EINTR.Это зависит от семантики перезапуска системного вызова и немного сложнее.

...