В
./binary < file
binary
sdin - это файл, открытый в режиме только для чтения. Обратите внимание, что bash
файл вообще не читается, он просто открывается для чтения по дескриптору файла 0 (stdin) процесса, в котором он выполняется binary
.
В:
./binary << EOF
test
EOF
В зависимости от оболочки, binary
stdin будет либо удаленным временным файлом (AT & T ksh, zsh, bash ...), который содержит test\n
как положено туда оболочкой, так и концом чтения канала ( dash
, yash
; и оболочка пишет test\n
параллельно на другом конце трубы). В вашем случае, если вы используете bash
, это будет временный файл.
В:
cat file | ./binary
В зависимости от оболочки, binary
stdin будет либо концом чтения канала, либо одним концом пары сокетов, где направление записи отключено (ksh93) и cat
записывает содержимое file
другого конца.
Когда stdin - обычный файл (временный или нет), он доступен для поиска. binary
может идти в начало или конец, перематывать и т. д. Он также может отображать его, делать что-то ioctl()s
вроде FIEMAP / FIBMAP (при использовании <>
вместо <
него он может обрезать / пробивать отверстия и т. д.).
трубы и пары сокетов, с другой стороны, являются средством межпроцессного взаимодействия, кроме данных мало что binary
можно сделать read
(хотя есть также некоторые операции, например, некоторые специфичные для канала, ioctl()
которые он может выполнять с ними, а не с обычными файлами) ,
В большинстве случаев, это недостающее способность , seek
что приводит к приложениям к сбою / жалуются при работе с трубами, но это может быть любой из других системных вызовов, которые действительны для обычных файлов , но не на различных типах файлов (как mmap()
, ftruncate()
, fallocate()
) , В Linux также есть большая разница в поведении, когда вы открываете, /dev/stdin
когда fd 0 находится в канале или в обычном файле.
Существует множество команд, которые могут работать только с доступными для поиска файлами, но в этом случае это обычно не относится к файлам, открытым на их стандартном диске.
$ unzip -l file.zip
Archive: file.zip
Length Date Time Name
--------- ---------- ----- ----
11 2016-12-21 14:43 file
--------- -------
11 1 file
$ unzip -l <(cat file.zip)
# more or less the same as cat file.zip | unzip -l /dev/stdin
Archive: /proc/self/fd/11
End-of-central-directory signature not found. Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive. In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
unzip: cannot find zipfile directory in one of /proc/self/fd/11 or
/proc/self/fd/11.zip, and cannot find /proc/self/fd/11.ZIP, period.
unzip
Необходимо прочитать индекс, хранящийся в конце файла, а затем выполнить поиск в файле для чтения членов архива. Но здесь файл (обычный в первом случае, труба во втором) задается в качестве аргумента пути unzip
и unzip
открывает его сам (обычно на fd, отличном от 0), вместо того, чтобы наследовать fd, уже открытый родителем. Он не читает zip-файлы со своего стандартного устройства. stdin в основном используется для взаимодействия с пользователем.
Если вы запустите свой binary
без перенаправления по приглашению интерактивной оболочки, запущенной в эмуляторе терминала, то binary
stdin будет унаследован от его родительской оболочки, которая сама унаследует его от своего родительского эмулятора терминала и будет Устройство pty открывается в режиме чтения + записи (что-то вроде /dev/pts/n
).
Эти устройства также не доступны для поиска. Таким образом, если binary
при работе с терминала все работает нормально, возможно, проблема не в поиске.
Если это 14 должно быть ошибочным (код ошибки, установленный при сбое системных вызовов), то в большинстве систем это будет EFAULT
( неверный адрес ). read()
Системный вызов потерпит неудачу с этой ошибкой , если попросил прочитать в адрес памяти , который не доступен для записи. Это будет зависеть от того, будет ли fd считывать данные из точек в канал или обычный файл, и обычно будет указывать на ошибку 1 .
binary
возможно определяет тип файла, открытого на его стандартном вводе (с fstat()
), и сталкивается с ошибкой, когда он не является ни обычным файлом, ни устройством tty.
Трудно сказать, не зная больше о приложении. Запуск его под strace
(или truss
/ или tusc
аналогичным образом в вашей системе) может помочь нам увидеть, что такое системный вызов, если он здесь не работает.
1 Сценарий, предусмотренный Мэтью Ифе в комментарии к вашему вопросу, звучит здесь очень правдоподобно. Цитирую его:
Я подозреваю, что он пытается до конца файла получить размер буфера для чтения данных, плохо обрабатывая тот факт, что поиск не работает, и пытается выделить отрицательный размер (не обрабатывая неверный malloc). Передача буфера для чтения, какие ошибки с учетом буфера недопустимы.