2016-12-18 3 views
2

У меня есть простая программа на C с функцией чтения, и я не понимаю выход.C Читайте в bash: stdin и stdout

//code1.c 
#include <unistd.h> 
#include <stdio.h> 
#include <fcntl.h> 
int main() 
{ 

    int r; 
    char c; // In C, char values are stored in 1 byte 

    r = read (0, &c, 1); 

    // DOC: 
    //ssize_t read (int filedes, void *buffer, size_t size) 
    //The read function reads up to size bytes from the file with descriptor filedes, storing the results in the buffer. 
    //The return value is the number of bytes actually read. 

    // Here: 
    // filedes is 0, which is stdin from <stdio.h> 
    // *buffer is &c : address in memory of char c 
    // size is 1 meaning it will read only 1 byte 

    printf ("r = %d\n", r); 

    return 0; 
} 

А вот скриншот результата:

Screenshot of program executio

Я побежал эту программу в 2 раза, как показано выше, и напечатал «а» для первой попытки и «aecho привет» для вторая попытка.

Как я пытаюсь объяснить результаты:?.

  1. Когда read называется он видит, что STDIN закрывается и открывается его (с моей точки зрения, почему он должен просто читать его я не знать, почему это открывает его).
  2. Я печатаю «aecho hi» в bash и нажимаю enter.
  3. read имеет приоритет для обработки stdin и считывает первый байт «aecho hi»: «a».
  4. Получаю подтверждение, что read обработал 1 байт с помощью printf.
  5. a.out завершено и завершено.
  6. Как-то остальные данные в stdin обрабатываются в bash (отце моей программы) и идут на stdout, который его выполняет, и по какой-то причине первый байт был удален read.

Это все гипотетическое и очень размытое. Любая помощь в понимании того, что происходит, была бы очень желанной.

+0

'stdin' открывается при запуске программы, а не только при вызове' read() '. Остальные ваши объяснения верны. – alk

+0

'stdin' не является« * процессом * », а потоком, как и' stdout'. – alk

+0

«* идет в stdout *». На самом деле, оболочка (bash здесь) перекликается с тем, что она читает через 'stdin', на' stdout', затем выполняет то, что она читает ('echo hi'), и печатает/записывает результат (' hi ') на' stdout'. – alk

ответ

1

Когда вы вводите свой эмулятор терминала, он записывает ваши нажатия клавиш в «файл», в этом случае буфер в памяти, который благодаря файловой системе выглядит так же, как и любой другой файл, который может быть на диске.

Каждый процесс наследует 3 открытых дескриптора файла от его родителя. Нас интересует один из них, стандартный ввод.Программа, выполняемая эмулятором терминала (здесь, bash), указывается в качестве стандартного ввода буфера в памяти, описанного в первом абзаце.

a.out, когда в ведении bash, также получает этот же файл, стандартного ввода. Имейте это в виду: bash и a.out читают из того же, уже открытого файла.

После запуска a.out его read блоков, поскольку его стандартный ввод пуст. Когда вы вводите aecho hi<enter>, терминал записывает эти символы в буфер (<enter>, становясь одним символом перевода строки). a.out только один символ, поэтому он получает a и оставляет остальные символы в файле. (Или, точнее, указатель файла все еще указывает на e после a чтения.)

После a.out Завершает, bash пытается прочитать из того же файла. Обычно файл пуст (т. Е. Указатель файла находится в конце файла), поэтому bash блокирует ожидание другой команды. В этом случае, однако, имеется уже доступный вход: echo hi\n. bash читает это сейчас так же, как если бы вы набрали его послеa.out завершено.

1

Проверить this. Поскольку алк предполагает, что stdin и stdout уже открыты с программой. Теперь вы должны понимать, как только вы наберете:

aecho hi 

и ударил вернуть stdin буфер заполняется всеми этими буквами (и пространство) - и будет продолжать быть до тех пор, пока вы не смывать его. Когда программа завершается, буфер stdin по-прежнему заполняется, и ваш терминал автоматически обрабатывает запись в stdin, повторяя ее до stdout - это то, что вы видите в конце - ваша оболочка читает stdin.

Теперь, когда вы указываете, ваш код «нажимает на возврат» для вас так сказать - в первом исполнении добавляется пустая строка оболочки, а во втором выполняется echo hi. Но вы должны помнить: вы нажали return, поэтому «\ n» находится в буфере! Для того, чтобы быть явным, вы на самом деле набрали:

aecho hi\n 

После программы выходит оболочка считывает оставшиеся символы в буфере, включая возвращение, и это то, что вы видите!

+0

Но почему прочитал покраснение «а» из «аэчо привет»? И в первом выполнении буфер пуст (при условии, что чтение очищено «a»). Тем не менее он по-прежнему выполняет пустую команду. – shrimpdrake

+0

Я не следую - в первом исполнении вы набрали 'a'. Это заполнило буфер «a», который читается, чем сбрасывает (да, читает, удаляет то, что он читает). Это способ чтения (как и большинство прочитанных вещей, вы хотите, чтобы следующий звонок читал следующее письмо, а не одно и то же - scanf, get и т. Д.). Тогда есть еще «\ n» - Return! Я отредактирую свой ответ, я забыл об этом. – kabanus

+0

Об «\ n»: «Я вынужден» нажать «Ввод», чтобы сказать, что я закончил заполнять этот ввод, если бы я смог обойти, что программа просто поместила бы остальную часть текста в stdout, которую я смог бы редактировать в bash (поскольку он еще не выполнялся с помощью \ n). Как мне это сделать ? – shrimpdrake

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