免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
1234下一页
最近访问板块 发新帖
查看: 18015 | 回复: 38
打印 上一主题 下一主题

用dup2()能关闭标准输出吗? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-04-11 10:52 |只看该作者 |倒序浏览
在APUE第三章中讲到
       dup2( filedes, filedes2 );  
is equivalent to
          close( filedes2 );
          fcntl( filedes, F_DUPFP, filesdes2 );

那为什么在执行下面这段代码时,还能打印出东西呢?

  1. #include <unistd.h>
  2. #include <stdio.h>
  3. int main()
  4. {
  5.         dup2(0, STDOUT_FILENO );       
  6.         printf("how!!\n" );
  7. }

复制代码


而执行下面这段代码时就没有打印出 how!!\n 了。


  1. #include <unistd.h>
  2. #include <stdio.h>
  3. int main()
  4. {
  5.         close( STDOUT_FILENO );
  6.         printf("how!!\n" );
  7. }

复制代码


希望高手能不吝赐教,谢了。

[ 本帖最后由 cu_liang 于 2008-4-11 11:39 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2008-04-11 12:34 |只看该作者
从strace的情况来看,dup2并没有实际想像那样操作。
在lighttpd里面是这样关闭stdin的。

  1. 575     /* close stdin and stdout, as they are not needed */
  2. 576     /* move stdin to /dev/null */
  3. 577     if (-1 != (fd = open("/dev/null", O_RDONLY))) {
  4. 578         close(STDIN_FILENO);
  5. 579         dup2(fd, STDIN_FILENO);
  6. 580         close(fd);
  7. 581     }
  8. 582
  9. 583     /* move stdout to /dev/null */
  10. 584     if (-1 != (fd = open("/dev/null", O_WRONLY))) {
  11. 585         close(STDOUT_FILENO);
  12. 586         dup2(fd, STDOUT_FILENO);
  13. 587         close(fd);
  14. 588     }
复制代码

[ 本帖最后由 swordfish.cn 于 2008-4-11 12:39 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2008-04-11 12:42 |只看该作者
楼上的解释我没看懂,关注ing

论坛徽章:
0
4 [报告]
发表于 2008-04-11 12:43 |只看该作者

  1. #include <string.h>
  2. #include <fcntl.h>

  3. int main () {
  4.     int fd;
  5.     fd = open("/dev/null", O_RDONLY);
  6.     close(STDOUT_FILENO);
  7.     dup2(fd, STDOUT_FILENO);
  8.     close(fd);
  9.     printf("%d\n", STDOUT_FILENO);
  10.     return 0;
  11. }
复制代码


这样strace之后即有

$ strace ./t
...
write(1, "1\n", 2)                      = -1 EBADF (Bad file descriptor)

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
5 [报告]
发表于 2008-04-12 00:06 |只看该作者

回复 #1 cu_liang 的帖子

判断一下 dup2 的返回值。

论坛徽章:
0
6 [报告]
发表于 2008-04-13 11:35 |只看该作者

回复 #5 MMMIX 的帖子

dup2的返回值是1,说明dup2函数应该是执行成功的了,但就是不知道为什么没有关闭标准输出了。


用strace命令好象也看不出什么东西来,
有谁知道dup2()在底层是怎么实现的吗?:em11: :em12:

[ 本帖最后由 cu_liang 于 2008-4-13 11:44 编辑 ]

论坛徽章:
0
7 [报告]
发表于 2008-04-13 13:13 |只看该作者
dup2是怎么实现的,看代码不就行了吗。
代码都是现成的。

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
8 [报告]
发表于 2008-04-13 19:31 |只看该作者
原帖由 cu_liang 于 2008-4-13 11:35 发表
dup2的返回值是1,说明dup2函数应该是执行成功的了,

dup2(2) 成功时返回 0。另外,dup2 是系统调用,而系统调用一般都是成功时返回 0,失败时返回 -1。

论坛徽章:
0
9 [报告]
发表于 2008-04-13 20:47 |只看该作者
原帖由 MMMIX 于 2008-4-13 19:31 发表

dup2(2) 成功时返回 0。另外,dup2 是系统调用,而系统调用一般都是成功时返回 0,失败时返回 -1。


M版,这个说法不对吧。在 manpage 中如是说:
RETURN VALUE
       dup() and dup2() return the new descriptor, or -1 if an error  occurred
       (in which case, errno is set appropriately).


所以返回 1 的话,那执行应该是成功了吧。
但是事实上的效果却又有不同,所以我只好把它看作一个特例了。

论坛徽章:
0
10 [报告]
发表于 2008-04-13 22:39 |只看该作者
原帖由 cu_liang 于 2008-4-11 10:52 发表
在APUE第三章中讲到
       dup2( filedes, filedes2 );  
is equivalent to
          close( filedes2 );
          fcntl( filedes, F_DUPFP, filesdes2 );

那为什么在执行下面这段代码时,还能打印出 ...


其实重点不是在dup2(),对于下面的代码:


  1. #include<stdio.h>
  2. #include<unistd.h>
  3. #include<fcntl.h>
  4. #include<sys/types.h>
  5. #include<stdlib.h>

  6. int main()
  7. {
  8.         close(STDOUT_FILENO);
  9.         write(0, "hello\n", 6);
  10.         return 0;
  11. }

复制代码

照样可以输出hello来。

而dup2()完成的功能是什么呢?它是让文件描述符的指针指向文件表。
当dup2(0, STDOUT_FILENO);时 首先关闭STDOUT_FILENO,也就是将标准输出关闭掉。此时再让STDOUT_FILENO描述符的指针指向STDIN_FILENO所指向的那个文件表。所以说对于楼主所列的第一个代码仍然可以输出也就是这样的原因。


  1. #include <unistd.h>
  2. #include <stdio.h>
  3. int main()
  4. {
  5.         dup2(0, STDOUT_FILENO );        
  6.         printf("how!!\n" );
  7. }
复制代码

此时STDIN_FILENO,STDOUT_FILENO两个都指向的是标准输入,也即是0的那个文件表,而这个又与终端相连,所以能够输出数据来。

不信你可以这样来试试,
gcc test.c -o test

./test 1>test.out
此时你可以看到那个how!!仍然是打印到终端而没有写入到test.out中,证明不是从标准输出得到的数据。

而如果
./test 0>test.out
你则可以看到那个how!!输出到了test.out文件中。证明是从标准输入这个描述符得到的数据。

不知道我说清楚没有?有什么大家再一起讨论。

评分

参与人数 1可用积分 +9 收起 理由
MMMIX + 9 精品文章

查看全部评分

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP