理解read()和write()的行为

时间:2010-06-04 06:36:03

标签: c linux

您好我是一名学生,刚开始学习低级c编程。我试图通过此程序了解read()write()方法。

#include <unistd.h>
#include <stdlib.h>
main()
{
    char *st;
    st=calloc(sizeof(char),2);//allocate memory for 2 char
    read(0,st,2);
    write(1,st,2);
}

当我尝试输入超过2个输入字符时,我预计它会给出分段错误。但是当我执行程序并在输出“as”后输入“asdf”时,它会执行“df”命令。

我想知道为什么当我们为一个大小为2的字符串分配超过2个字符时它不会给出分段错误。为什么它将输入的rest(在2 char之后)作为命令执行而不是将其作为输出仅?

还阅读read()的man page我发现read()应该给出EFAULT错误,但它没有。

我正在使用linux。

5 个答案:

答案 0 :(得分:3)

你的read明确指出它只需要两个字符就可以了。您将更多字符添加到st区域,这样您就不会违反任何分段。

至于为什么它正在执行df部分,这实际上不会发生在我的直接系统上,因为程序一直挂起,直到按下ENTER,并且看起来程序的I / O正在吸收额外的数据。但是,即时系统是Cygwin - 请参阅下面的更新,了解“真正的”UNIX机箱上的行为。

如果EFAULT超出您的地址空间或无效,您将获得st。情况并非如此。


更新

在Ubuntu 9上尝试这个,我看到行为与你的相同。当我提供字符asls时,程序输出as然后执行目录列表

这意味着你的程序只读取两个字符,剩下的就是“下一个”程序要读取,这就是shell。

请确保您不要尝试输入:

asrm -rf /

(不,严肃地说,那样做。)

答案 1 :(得分:2)

您要求read()读取不超过2个字符(第三个参数到read()),因此它会覆盖您提供的缓冲区中不超过两个字符。这就是为什么没有任何错误行为的原因。

答案 2 :(得分:1)

读取()时,指定所需的字节数。除非你的libc坏了,否则你不会得到更多,所以只要你的计数永远不会超过你的缓冲区的大小,你就永远不会超出缓冲区的末尾。额外的字节保留在流中,下一个read()将获得它们。如果您的应用程序中没有下一个read(),则生成它的过程(通常是shell)可能会看到它们,因为从shell生成控制台应用程序涉及将shell的输入和输出流附加到这个过程。 shell是否看到并获取字节部分取决于libc在幕后进行了多少缓冲,以及它是否能够/“取消”退出时的任何缓冲字节。

答案 3 :(得分:0)

with read(0,st,2);你从标准输入读取2个字符。 你键入的其他内容将不会被程序所控制,但不会被省略,因此击键将返回到程序启动的shell(df并输入)。

答案 4 :(得分:0)

由于你只读了2个字符,所以没有问题。 df字符不会被你的程序占用,因此它们会留在终端缓冲区中,并由shell使用:

  • 你的程序运行
  • 您输入asdf\n
  • 您的程序读取as并将df\n留在tty缓冲区
  • 您将st缓冲区的内容写入stdout
  • 您的计划停止
  • shell从输入中读取df\n并执行df命令。

有趣的事情:

  • 截取您的程序,以跟踪系统调用:strace -e read, write ./yourprogram
  • read(0, st, 5)
相关问题