Ваш исходный код создает своего рода условие гонки между родительским и дочерним процессами и оболочкой, которая запустила вашу программу. Процесс ls
завершается до того, как more
сможет прочитать все данные из канала, и поскольку в вашей программе родительский процесс заменяется процессом ls
, когда этот процесс ls
завершается (после записи всех его выходных данных в буфер канала), который он закрывает, и при этом закрывает канал и возвращает управление оболочке, которая сразу же готовится прочитать другую команду.
Итак, изначально и more
, и оболочка могут читать с того же устройства TTY (оно читает из своего дескриптора STDERR
, все еще подключенного к вашему TTY), а затем, когда more
в конечном итоге получает какой-либо ввод, он снова попытается прочитать из канала (его STDIN
) и получить конец файла (канал был закрыт в конце записи при выходе из ls
), и поэтому more
теперь также завершится (без вывода дополнительных выводов). Существует также возможная гонка между процессом more
и оболочкой в отношении того, какие (пере) установки режимов драйвера TTY и когда.
Альтернативная реализация вашей программы для исходного родительского процесса для запуска двух дочерних процессов. процессы, один для more
и один для ls
, а затем ждать завершения обоих процессов, но для этого, конечно, потребуются дополнительные системные ресурсы.