当前位置:  技术问答>linux和unix

dup2后的奇异现象

    来源: 互联网  发布时间:2017-02-27

    本文导语:  我写了这样一个程序: #include  #include  #include  int main( ) {   int fd = open("file", O_CREAT|O_WRONLY, 0644);   int newfd = dup(1);   dup2(fd, 1);   close(fd);   printf("hellon");   dup2(newfd, 1);   printf("worldn");   return 0; } 本来...

我写了这样一个程序:
#include 
#include 
#include 

int main( )
{
  int fd = open("file", O_CREAT|O_WRONLY, 0644);
  int newfd = dup(1);
  dup2(fd, 1);
  close(fd);
  printf("hellon");
  dup2(newfd, 1);
  printf("worldn");
  return 0;
}

本来期待程序运行时会把"hellon"写入到文件file中,把"worldn"输出到屏幕上,但结果却是都在屏幕上。如果没有倒数第四行的dup2函数调用,就会都写入到文件file中。
跟踪系统调用的结果发现两个printf的输出的字符串内容被合在一起调用的write。也就是说,printf遇到n并没有清缓冲。
但更奇怪的问题在于,只要在main函数中第一个dup2调用之前的任何一行插入一个printf调用,后面的输出就不会合并,而是像我先前预期的那样把"hellon"写入到文件file中,把"worldn"输出到屏幕上了。

求高手解惑!

环境:ubuntu和fedora都是如此。

|
#include 
#include 
#include 

        int main( )
        {
                printf("startn");
                  int fd = open("file", O_CREAT|O_WRONLY, 0644);
                    int newfd = dup(1);
                          dup2(fd, 1);
                            close(fd);
                  
                                printf("hellon");
                                    dup2(newfd, 1);
                                          printf("worldn");
                                            return 0;
        }


我测了一下,manpage setvbuf了一下,得出结论,任意一个FILE*,在首次操作它的时候,它会fstat判断fd的类型,如果是文件就设置FILE为全缓冲,是终端就行缓冲,否则全缓冲。

这里你在第一次操作stdout时,它的fd已经是文件了,所以printf会做首次检测,设置它为全缓冲。

所以我在行首做了一个printf操作,让FILE先被设置为行缓冲,因为这是第一次操作stdout,并且fileno(stdout)是与终端关联的。

|
 When the first I/O operation  occurs
       on a file, malloc(3) is called, and a buffer is obtained.  If a stream refers to a terminal (as stdout normally does) it is line buffered.  The standard
       error stream stderr is always unbuffered by default.

|
楼上正确, , 
应该是由行缓冲变为了全缓冲。
验证如下:
至于你说的在第二个dup2前加个printf的话,hello 输出到文件,world输出到屏幕 的事。。 我试验了仍然是都输出到屏幕 。使用的环境是ubuntu 12.04 LTS. 
理解这个行缓冲和全缓冲就行了。 不用太纠缠于太细节的东西 , 因为有些是和实现有关的。 若标准未规定, 则和各自的实现有关 (glibc库的实现)

#include 
#include 
#include 

int main( )
{
  int fd = open("file", O_CREAT|O_WRONLY, 0644);
  int newfd = dup(1);
  dup2(fd, 1);
  close(fd);
  setlinebuf(stdout);
  printf("hellon");
  dup2(newfd, 1);
  printf("worldn");
  return 0;
}

|
怀疑是标准输出重定向到文件中之后,缓冲方式由原来的行缓冲变为了全缓冲

    
 
 

您可能感兴趣的文章:

 
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 哪位大侠帮忙写一个函数dup1()实现dup2()的功能!或者直接提供dup2()的源码??
  • 关于dup2的一个问题
  • 关于dup2的问题!
  • UNIX环境下,如何实现dup2函数,不允许调用fcntl?
  • dup2的问题,百思不得其解,求教,谢谢
  • dup2 问题
  • 初学u编程,问个dup2的问题
  • Unix高级环境编程一有关dup2的习题,求解释!!!!
  • APUE初学者:请问dup,dup2函数可以用来干什么?有什么好处?
  • dup2函数问题
  • dup2(fd[0],STDIN_FILENO)!=STDIN_FILENO疑问
  • 利用fork 与 dup2 执行 系统命令, 别的命令都可以获取执行结果,就fdisk 命令不可以. execve("/sbin/fdisk",args,NULL) , args 命令参数.
  • 哪位老大能讲一下lseek函数和dup与dup2函数是干什么用的,最好有实例
  • 急: 代码那里写错了??dup2 execve写的执行命令的程序, 重定向标准输入、输出、标准错误,无法获取到fdisk 的命令输出。别的命令都可以。附代码


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3