stdin、stdout和STDIN_FILENO、STDOUT_FILENO

来源:互联网 发布:淘宝联盟qq推广 编辑:程序博客网 时间:2024/05/29 04:07

这周末开始看《APUE》,和《linux内核设计与实现》、《深入理解linux内核》同步往前推进。

图1-4代码中用到了

while ((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0)                if (write(STDOUT_FILENO, buf, n) != n)                        err_sys("write error");

书中描述为:两个常量STDIN_FILENO和STDOUT_FILENO定义在<unistd.h>头文件中,它们指定了标准输入和标准输出的文件描述符。

刚开始误解为:只要在read和write的参数中传入这两个描述符,那么就不再是文件IO(低级IO)了,而改为标准IO(高级IO)了。

其实不是酱紫,而是:

只要调用的是read()write()函数,那就一定是文件IO操作。

而标准IO操作对应的则是stdin,stdout,stderr。

这里说的“标准”IO,与上面说的“指定了标准输入和标准输出的文件描述符”的“标准”二字概念不一样。


下面总结一下二者区别,五个区别对比参考:

I (stdin,stdout,stderr):

  • stdin等是FILE *类型;是C中的标准输入输出流,缓冲方式进行。
  • 属于标准I/O(是C语言标准输入输出流),是文件流方式。属于高级I/O,带缓冲;
  • 在<stdio.h>。
  • 使用stdin等的函数主要有:fread、fwrite、fclose等标准库调用,基本上都以f开头。
  • stdin等由用户层的标准C库实现;提供的文件操作函数库都是用FILE*来表示文件,stdin等就是指向标准输入设备文件的FILE*。

II (STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO):

  • STDIN_FILENO等是int类型;是文件描述符,一般定义为0, 1,2;
  • 属于系统API接口库(是linux OS文件读写描述符);没有buffer的I/O,直接调用系统调用。属于低级IO,要自己处理缓冲。
  • 在<unistd.h>。
  • 使用STDIN_FILENO等的函数有:read、write、close等
  • STDIN_FILENO等用于系统层的系统调用,操作系统级提供的文件API都是以文件描述符来表示文件。STDIN_FILENO就是标准输入设备(一般是键盘)的文件描述符。


III (二者的联系):

标准库内封装了系统 API 调用,如 fread 内部实现调用 read

例如:

printf的调用流程

printf -> stdout -> STDOUT_FILENO(1) -> 终端(tty) 

通常守护进程在后台运行,所以要将它的标准输入输出重定向到/dev/null


在linux下,stdin等的实现必然依赖于文件描述符。

也就是说这两个东西在不同的层次,一个是用户层的C库,一个是系统层的系统调用。

程序启动时:

FILE * stdin / stdout / stderr 对应的文件描述符(fd)分别是 STDIN_FILENO(0) / STDOUT_FILENO(1) / STDERR_FILENO(2) 。

但是,可以通过FILE *freopen(const char *path, const char *mode, FILE *stream); 来改变,使文件描述符(fd)对应到其他的stream上。


(对于“流”的理解,以后写文)




参考:http://bbs.csdn.net/topics/240009889


0 0
原创粉丝点击