В
./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 знаходиться на трубі або у звичайному файлі.
Існує багато команд, які можуть працювати лише з файлами, які шукаються , але коли це так, це, як правило, не для файлів, відкритих на їхньому stdin.
$ 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. Він не читає поштові файли зі свого stdin. stdin здебільшого використовується для взаємодії з користувачем.
Якщо ви запускаєте цю binary
свою без перенаправлення під запит інтерактивної оболонки, що працює в емуляторі терміналу, то binary
stdin буде успадкований від свого батьківського оболонки, який сам успадкував його від свого батьківського термінального емулятора і буде pty пристрій відкрито в режимі читання + запису (щось подібне /dev/pts/n
).
Ці пристрої також не можна знайти. Отже, якщо binary
працює нормально, коли приймається вхід з терміналу, можливо, питання не в тому, щоб шукати.
Якщо це 14 мається на увазі помилка (код помилки, встановлений невдачею системних викликів), то для більшості систем це буде EFAULT
( неправильна адреса ). read()
Системний виклик зазнає невдачі з цією помилкою , якщо попросив прочитати на адресу пам'яті , який не доступний для запису. Це не залежатиме від того, чи буде fd читати дані з пунктів до труби чи звичайного файлу, і загалом би вказувало на помилку 1 .
binary
можливо, визначає тип файлу, відкритого на його stdin (with fstat()
), і потрапляє в помилку, коли він не є ні звичайним файлом, ні tty пристроєм.
Важко сказати, не знаючи більше про додаток. Запуск його під strace
(або truss
/ tusc
еквівалент у вашій системі) може допомогти нам зрозуміти, що таке системний виклик, якщо якийсь тут не працює.
1 Сценарій, передбачений Метью Іфе у коментарі до вашого питання, тут звучить дуже правдоподібно. Цитуючи його:
Я підозрюю, що він прагне до кінця файлу отримати розмір буфера для зчитування даних, погано поводячись з тим, що пошук не працює, і намагається виділити негативний розмір (не обробляючи поганий malloc). Передача буфера, щоб прочитати, які помилки в даному буфері не є дійсними.