2015-10-15 3 views
3

Предположим следующий простой код:Где ядру Linux хранить данные, записанные на трубе

#include <stdio.h> 
#include <unistd.h> 
#include <sys/types.h> 

main() 
{ 
    int fd[2];     
    pipe(fd); 
// ...    
    write(fd, buf, VERY_BIG_NUMBER); 
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
} 

Теперь мои вопросы:

  1. Может кто-нибудь объяснить, где запись будет помещать данные?
  2. Записывается ли он в буфер, расположенный в пространстве пользователя или в пространстве ядра?
  3. Какова максимальная длина, которую можно записать в трубу?
  4. Поскольку запись в трубе блокирует работу, не будет ли ядро ​​для эффективности просто ничего не делать и ждать, пока читатель передаст данные прямо ему?
+1

[7 человек труба] (http://man7.org/linux/man-pages/man7/pipe.7.html) – rici

+0

@rici Я просто консультировались человека 2, спасибо за указание правильной страницы. – redobot

ответ

6

Существует буфер для труб, обычно 64 КБ на Linux. Записывает буфер буфера. Как только он будет заполнен, блок write() блокируется, пока другой конец трубы не разрядит буфер.

Выдержка из pipe(7) man page:

Труба имеет ограниченную емкость. Если труба заполнена, тогда запись (2) будет блокироваться или сбой, в зависимости от того, установлен ли флаг O_NONBLOCK (см. Ниже). Различные варианты исполнения имеют разные пределы пропускной способности трубопровода. Приложения не должны полагаться на определенную емкость: приложение должно быть спроектировано так, чтобы процесс чтения потреблял данные, как только он был доступен, чтобы процесс записи не блокировался.

В версиях Linux до версии 2.6.11 емкость канала была такой же, как размер системной страницы (например, 4096 байт на i386). Начиная с Linux 2.6.11, емкость канала составляет 65536 байт.

Буфер находится в пространстве ядра. Трубы реализуются через виртуальную файловую систему pipefs. Код ядра для этой файловой системы выделяет 16 страниц 4 КБ для каждого системного вызова pipe2(), и это буферное пространство связано с inode, созданным для этого канала. read() и write() syscalls копирует данные в и из пользовательского пространства. (Source)

Запись на трубу является атомной, если она меньше 4 КБ. Запись более 4 КБ может привести к ошибкам страницы и, следовательно, больше не является атомарной. Это означает, что множественные записи из отдельных процессов могут чередоваться, если записи больше 4 КБ.

Смотрите также:How big is the pipe buffer?

Смежные вопросы