C语言write()函数为何将文件描述符0也视为标准输出?

C语言write()函数文件描述符传0,为什么还是会写入到标准输出(屏幕上)

write的声明如下

ssize_t write(int fd, const void *buf, size_t count);

可以看到第一个参数应该是文件描述符(windows下叫句柄),然后通常情况下,进程会将0初始化为标准输入,将1初始化为标准输出

# define stdin  0
# define stdout 1

但是不知道为什么write这个函数的行为似乎有些诡异,我做了这样一个实验

#include <unistd.h>
#include <string.h>

int main() {
    char *message1 = "Writing to stdout using file descriptor 0\n";
    char *message2 = "Writing to stdout using file descriptor 1\n";

    write(0, message1, strlen(message1));
    write(1, message2, strlen(message2));

    return 0;
}

正常来讲我感觉write函数应该只有message2是可以正常打印的,message1理论上来说会报错,
因为理论上来讲write函数应该是无法写入0(stdin)的, 可是程序编译和运行却完全没有任何问题,这是运行结果

$ gcc test.c
$ ./a.out  
Writing to stdout using file descriptor 0
Writing to stdout using file descriptor 1

所以我想问一下有没有大佬知道为什么write函数文件描述符传0也会写入标准输出(stdout)


备注:我的平台是ubuntu 22.04,gcc版本是gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0

阅读 1.4k
1 个回答
新手上路,请多包涵

1.write函数属于linux提供的系统调用,这个函数是没有缓冲区的,直接写到fd对应文件在内存中的文件结构体中的缓冲区。
2.文件结构体维护着一个缓冲区,由操作系统决定何时将此缓冲区的内容写到文件在内存的拷贝。
3.键盘也是一个文件,不过大多数情况对于操作系统而言是一个只读文件,我们输入的本质上时字符串,先存在文件结构体的缓冲区,再由操作系统决定何时将这串字符串读到进程里面。
3.stdin=0,当尝试往stdin里面写入字符串时,实际上这个字符串先保存在键盘文件缓冲区,而键盘接收不了字符串,于是这段字符停在缓冲区,而操作系统会认为这是键盘输入的字符,打印在屏幕上。
如下图
image.png
在sleep的10s内,我在键盘上输入字符,命令行也会打印我输入的东西。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏