C读入bash:stdin和stdout

时间:2016-12-18 14:51:14

标签: c bash ubuntu buffer

我有一个带读取功能的简单C程序,我不理解输出。

//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次,然后键入&#34; a&#34;第一次尝试和&#34; aecho hi&#34;第二次尝试。

我如何尝试解释结果:

  1. 当调用read时,它会看到stdin已关闭并打开它(从我的角度来看,为什么?它应该只读它。我不知道为什么打开它)。
  2. 我输入&#34; aecho hi&#34;在bash中按下回车。
  3. read优先处理stdin并读取&#34; aecho hi&#34;的第一个字节。 :&#34; a&#34;。
  4. 我得到read已使用printf处理了1个字节的确认。
  5. a.out已经完成并被终止。
  6. stdin中的剩余数据以bash(我程序的父亲)处理,然后转到执行它的stdout,由于某种原因,第一个字节已被read删除。
  7. 这都是假设的,非常模糊。任何有助于了解正在发生的事情的人都会非常欢迎。

2 个答案:

答案 0 :(得分:2)

当您在终端模拟器上键入时,它会将您的击键写入&#34;文件&#34;,在这种情况下是一个内存缓冲区,由于文件系统,它看起来就像任何其他可能的文件一样在磁盘上。

每个进程都从其父进程继承3个打开的文件句柄。我们感兴趣的是其中一个,标准输入。终端仿真器执行的程序(此处为bash)作为标准输入给出了第一段中描述的内存缓冲区。

a.out,当由bash运行时,会收到与标准输入相同的文件。请记住这一点:basha.out正在读取已经打开的文件。

运行a.out后,其read阻止,因为其标准输入为空。键入aecho hi<enter>时,终端会将这些字符写入缓冲区(<enter>成为单个换行符)。 a.out仅请求一个字符,因此它会获得a并将剩余的字符留在文件中。 (或者更准确地说,在读取e之后,文件指针仍然指向a。)

a.out完成后,bash会尝试从同一个文件中读取。通常,文件为空(即文件指针位于文件末尾),因此bash阻塞等待另一个命令。但是,在这种情况下,已有输入:echo hi\nbash现在读取此内容就像在 a.out完成后输入一样。

答案 1 :(得分:1)

检查this。正如alk所说,stdin和stdout已经在程序中打开了。输入后,您必须了解:

aecho hi

并点击返回stdin缓冲区中填充了所有这些字母(和空格) - 并且只要您不刷新它就会继续。当程序退出时,stdin缓冲区仍然已满,并且终端通过回显stdin自动处理对stdout的写入 - 这就是你最后看到的 - 你的shell读取{ {1}}。

现在正如你所指出的那样,你的代码“按回车”可以这么说 - 在第一次执行时添加一个空的shell行,在第二次执行stdin。但是你必须记住,你按了返回,所以“\ n”在缓冲区中!明确地说,你实际输入了:

echo hi

程序退出后,shell会读取缓冲区中剩余的字符,包括返回,这就是你所看到的!