Системные вызовы read и write

Прототипы системных вызовов

#include <sys/types.h>
#include <unistd.h>
size_t read(int fd, void *addr, size_t nbytes);
size_t write(int fd, void *addr, size_t nbytes);

Описание системных вызовов

Системные вызовы read и write предназначены для осуществления потоковых операций ввода (чтения) и вывода (записи) информации над каналами связи, описываемыми файловыми дескрипторами, т.е. для файлов, pipe'ов, FIFO и socket'ов.

Параметр
fd является файловым дескриптором созданного ранее потокового канала связи через который будет отсылаться или получаться информация, т. е. значением, которое вернул один из системных вызовов open(), pipe() или socket().
Параметр
addr представляет собой адрес области памяти, начиная с которого будет браться информация для передачи или размещаться принятая информация.
Параметр
nbytes для системного вызова write определяет количество байт, которое должно быть передано, начиная с адреса памяти addr. Параметр nbytes для системного вызова read определяет количество байт, которое мы хотим получить из канала связи и разместить в памяти, начиная с адреса addr.

Возвращаемые значения

В случае успешного завершения системный вызов возвращает количество реально отосланных или принятых байт. Заметим, что это значение (большее или равное 0) может не совпадать с заданным значенем параметра nbytes, а быть меньше, чем оно, в силу отсутствия места на диске или в линии связи при передаче данных или отсутствия информации при ее приеме. При возникновении какой-либо ошибки возвращается отрицательное значение.

Особенности поведения при работе с файлами

При работе с файлами информация записывается в файл или читается из файла, начиная с места, определяемого указателем текущей позиции в файле. Значение указателя увеличивается на количество реально прочитанных или записанных байт. При чтении информации из файла она не пропадает из него. Если системный вызов read возврашает значение 0, то это означает, что достигнут конец файла.

Особенности поведения при работе с pipe'ами, FIFO и socket'ами

Системный вызов read

Ситуация Поведение

Попытка прочитать меньше байт чем есть в наличии в канале связи

Читает требуемое количество байт и возвращает значение, соответствующее прочитанному количеству. Прочитанная информация удаляется из канала связи.

В канале связи находится меньше байт, чем затребовано, но не нулевое количество.

Читает все, что есть в канале связи, и возвращает значение, соответствующее прочитанному количеству. Прочитанная информация удаляется из канала связи.

Попытка читать из канала связи, в котором нет информации. Блокировка вызова разрешена.

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

Попытка читать из канала связи, в котором нет информации. Блокировка вызова не разрешена.

Если есть процессы, у которых канал связи открыт для записи, системный вызов возвращает значение -1 и устанавливает переменную errno в значение EAGAIN. Если таких процессов нет, системный вызов возвращает значение 0.


Системный вызов write

Ситуация Поведение

Попытка записать в канал связи меньше байт, чем осталось до его заполнения.

Требуемое количество байт помещается в канал связи, возвращается записанное количество байт.

Попытка записать в канал связи больше байт, чем осталось до его заполнения. Блокировка вызова разрешена.

Вызов блокируется до тех пор, пока все данные не будут помещены в канал связи. Если размер буфера канала связи меньше, чем передаваемое количество информации, то вызов тем самым будет ждать, пока часть информации не будет отчитана из канала связи. Возвращается записанное количество байт.

Попытка записать в канал связи больше байт, чем осталось до его заполнения, но меньше, чем размер буфера канала связи. Блокировка вызова запрещена.

Системный вызов возвращает значение -1 и устанавливает переменную errno в значение EAGAIN.

В канале связи есть место. Попытка записать в канал связи больше байт, чем осталось до его заполнения, и больше, чем размер буфера канала связи. Блокировка вызова запрещена.

Записывается столько байт, сколько осталось до заполнения канала. Системный вызов возвращает количество записанных байт.

Попытка записи в канал связи, в котором нет места. Блокировка вызова не разрешена.

Системный вызов возвращает значение -1 и устанавливает переменную errno в значение EAGAIN.

Попытка записи в канал связи, из которого некому больше читать, или полное закрытие канала на чтение во время блокировки системного вызова.

Если вызов был заблокирован, то он разблокируется. Процесс получает сигнал SIGPIPE. Если этот сигнал обрабатывается пользователем, то системный вызов вернет значение -1 и установит переменную errno в значение EPIPE.