Книга: Разработка приложений в среде Linux. Второе издание
11.2.5. Частичное чтение и запись
11.2.5. Частичное чтение и запись
Хотя обе функции — и read()
, и write()
— принимают параметр, указывающий, сколько байт нужно прочитать или записать, ни одна из них не гарантирует, что обработает указанное количество байт, даже если не случается никаких ошибок. Простейший пример этого — попытки чтения из обычного файла, который уже позиционирован в конце. Система не может прочитать ни одного байта, но это в то же время не является ошибкой. Вместо этого read()
возвращает 0 байт. Точно так же, если текущая позиция находилась в 10 байт от конца файла, и была выполнена попытка прочитать из файла более 10 байт, то прочитано будет ровно 10 байт и вызов read()
вернет число 10. Опять-таки это не рассматривается как ошибочная ситуация.
Поведение read()
также зависит от того, был ли файл открыт с флагом O_NONBLOCK
. Для файлов многих типов O_NONBLOCK
не влияет ни на что. Файлы, для которых система может гарантировать завершенность операции в пределах разумного периода времени, всегда блокирует чтение и запись; такие файлы часто называют быстрыми файлами. Это множество файлов включает локальные блочные устройства и обычные файлы. Для других типов файлов, таких как каналы, и символьных устройств вроде терминалов процесс может ожидать другого процесса (или человека), чтобы тот либо выполнил чтение, либо освободил ресурсы системы при обработке запроса на write()
. В обоих случаях система не имеет способа знать — будет ли вообще возможно дождаться завершения системного вызова. Когда такие файлы открываются с флагом O_NONBLOCK
, то для каждой операции с файлом система просто делает максимум того, что удается сделать немедленно, а затем возвращает управление вызывающему процессу.
Неблокирующий ввод-вывод — это важная тема, и больше примеров вы найдете в главе 13. После стандартизации системного вызова poll()
, однако, необходимость в нем (особенно при чтении) минимизирована. Если вам нужно интенсивно использовать неблокирующий ввод-вывод, попробуйте пересмотреть свою программу в терминах poll()
, чтобы увидеть, нельзя ли ее сделать более эффективной.
Чтобы показать конкретный пример чтения и записи файлов, приведем простую реализацию cat
. Она копирует стандартный поток ввода (stdin) на стандартный вывод (stdout) до тех пор, пока есть что копировать.
1: /* cat.с */
2:
3: #include <stdio.h>
4: #include <unistd.h>
5:
6: /* Пока есть данные на стандартном входе (fd0), копировать их в
7: стандартный выход (fd1). Выйти, когда не будет доступных данных. */
8:
9: int main(void) {
10: char buf[1024];
11: int len;
12:
13: /* len будет >= 0, пока доступны данные
14: и read() успешен */
15: while ((len = read(STDIN_FILENO, buf, sizeof(buf))) > 0) {
16: if (write(1, buf, len) != len) {
17: perror("write");
18: return 1;
19: }
20: }
21:
22: /* len будет <= 0; если len = 0, больше нет
23: доступных данных. Иначе - ошибка. */
24: if (len < 0) {
25: perror("read");
26: return 1;
27: }
28:
29: return 0;
30: }
- 4.4.3. Чтение и запись
- 1.18. Запись телефонных звонков
- Как сделать перезапись файлов в Проводнике более удобной?
- Не могу войти в систему под учетной записью администратора, поскольку среди имен пользователей, отображаемых на экране п...
- При попытке войти в систему Пользователю1 выдается предупреждение, что загрузился временный профиль и все сделанные изме...
- У файла и каталога есть атрибуты (например: Скрытый, Только чтение). Как ими управлять из командной строки?
- 12.5. Чтение «битых» компакт-дисков
- 19.2.4. Чтение и запись значений элементов HTML-форм
- 19.2.5. Чтение и запись содержимого элемента
- 1.2. Запись образа операционной системы на флэшку
- Запись звукового компакт-диска
- 19.2.1. Чтение и запись значений HTML-атрибутов