dup,dup2函数【转】
转自:http://eriol.iteye.com/blog/1180624
转自:http://www.cnblogs.com/jht/archive/2006/04/04/366086.html
dup和dup2也是两个非常有用的调用,它们的作用都是用来复制一个文件的描述符。它们经常用来重定向进程的stdin、stdout和stderr。这两个函数的原形如下:
- #include <unistd.h>
- int dup( int oldfd );
- int dup2( int oldfd, int targetfd );
dup()函数
利用函数dup,我们可以复制一个描述符。传给该函数一个既有的描述符,它就会返回一个新的描述符,这个新的描述符是传给它的描述符的拷贝。这意味着,这两个描述符共享同一个数据结构。例如,如果我们对一个文件描述符执行lseek操作,得到的第一个文件的位置和第二个是一样的。下面是用来说明dup函数使用方法的代码片段:
- int fd1, fd2;
- ...
- fd2 = dup( fd1 );
需要注意的是,我们可以在调用fork之前建立一个描述符,这与调用dup建立描述符的效果是一样的,子进程也同样会收到一个复制出来的描述符。
dup2()函数
dup2函数跟dup函数相似,但dup2函数允许调用者规定一个有效描述符和目标描述符的id。dup2函数成功返回时,目标描述符(dup2函数的第二个参数)将变成源描述符(dup2函数的第一个参数)的复制品,换句话说,两个文件描述符现在都指向同一个文件,并且是函数第一个参数指向的文件。下面我们用一段代码加以说明:
- int oldfd;
- oldfd = open("app_log", (O_RDWR | O_CREATE), 0644 );
- dup2( oldfd, 1 );
- close( oldfd );
在本例中,我们打开了一个新文件,称为“app_log”,并收到一个文件描述符,该描述符叫做fd1。我们调用dup2函数,参数为oldfd和1,这会导致用我们新打开的文件描述符替换掉由1代表的文件描述符(即stdout,因为标准输出文件的id为1)。任何写到stdout的东西,现在都将改为写入名为“app_log”的文件中。需要注意的是,dup2函数在复制了oldfd之后,会立即将其关闭,但不会关掉新近打开的文件描述符,因为文件描述符1现在也指向它。
例子
下面我们介绍一个更加深入的示例代码。回忆一下命令行管道,我们可以将ls –l命令的标准输出作为标准输入连接到wc –l命令。接下来,我们就用一个C程序来加以说明这个过程的实现。代码如下所示。
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- int main()
- {
- int pfds[2];
- if ( pipe(pfds) == 0 ) {
- if ( fork() == 0 ) {
- close(1);
- dup2( pfds[1], 1 );
- close( pfds[0] );
- execlp( "ls", "ls", "-l", NULL );
- } else {
- close(0);
- dup2( pfds[0], 0 );
- close( pfds[1] );
- execlp( "wc", "wc", "-l", NULL );
- }
- return 0;
- }
在示例代码中,首先在第9行代码中建立一个管道,然后将应用程序分成两个进程:一个子进程(第13–16行)和一个父进程(第20–23行)。接下来,在子进程中首先关闭stdout描述符(第13行),然后提供了ls –l命令功能,不过它不是写到stdout(第13行),而是写到我们建立的管道的输出端,这是通过dup2函数来完成重定向的。在第14行,使用dup2 函数把stdout重定向到管道(pfds[1])。之后,马上关掉管道的输入端。然后,使用execlp函数把子进程的映像替换为命令ls –l的进程映像,一旦该命令执行,它的任何输出都将发给管道的输入端。
现在来研究一下管道的接收端。从代码中可以看出,管道的接收端是由父进程来担当的。首先关闭stdin描述符(第20行),因为我们不会从机器的键盘等标准设备文件来接收数据的输入,而是从其它程序的输出中接收数据。然后,再一次用到dup2函数(第21行),让管道的输入端作为输入,这是通过让文件描述符0(即常规的stdin)重定向到pfds[0]实现的。关闭管道的stdout端(pfds[1]),因为在这里用不到它。最后,使用 execlp函数把父进程的映像替换为命令wc -l的进程映像,命令wc -l把管道的内容作为它的输入(第23行)。
这两个函数的功能是输出的重定向
定义这两个函数的头文件是unistd.h,有兴趣的可以自己看看这个头文件包含的内容
要提的是这个头文件同时定义了下面三个常量
STDERR_FILENO= 2 标准错误输出STDIN_FILENO= 0 标准输入STDOUT_FILENO= 1 标准输出
兄弟们学习网络编程用0,1,2这些参数的时候也得知道代表的意思
要说这两个函数的意思,还是看一段具体的代码
int fd, fd2;
mode_t fd_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;
void redir_stdout(const char *filename)
{
fd2=dup(STDOUT_FILENO);
fd = open(filename, O_WRONLY|O_CREAT, fd_mode); //打开文件操作
dup2(fd, STDOUT_FILENO); //把输出重定向到fd标识的文件
close(fd);
} fd2=dup(STDOUT_FILENO);说明fd2表示了标准输出
如果我们想把刚刚定向到fd的输出,再定向回标准输出,我们可以用下面的代码实现:
void resume_stdout() //恢复输出,把标准输出定向到fd2,fd2代表的是标准输出
{
dup2(fd2, STDOUT_FILENO);
close(fd2);
} dup,dup2函数【转】的更多相关文章
- linux下dup/dup2函数的用法
系统调用dup和dup2能够复制文件描述符.dup返回新的文件文件描述符(没有用的文件描述符最小的编号).dup2可以让用户指定返回的文件描述符的值,如果需要,则首先接近newfd的值,他通常用来重新 ...
- linux之dup和dup2函数解析
1. 文件描述符在内核中数据结构在具体说dup/dup2之前,我认为有必要先了解一下文件描述符在内核中的形态.一个进程在此存在期间,会有一些文件被打开,从而会返回一些文件描述符,从shell中运行一个 ...
- dup和dup2应用实例(dup跟APUE有出入,close+dup=dup2?)
dup/dup2函数 有时我们希望把标准输入重定向到一个文件,或者把标准输出重定向到一个网络连接. dup()与dup2()能对输入文件描述符进行重定向. 函数原型如下: dup函数创建一个新的文件描 ...
- dup和dup2函数
下面两个函数都可用来复制一个现存的文件描述符: #include<unistd.h> int dup(int filedes); int dup2(int filedes,int file ...
- dup和dup2函数以及管道的实现
疑问:管道应该不是这样实现的,因为这要求修改程序的代码 dup和dup2也是两个非常有用的调用,它们的作用都是用来复制一个文件的描述符.它们经常用来重定向进程的stdin.stdout和stderr. ...
- Unix 网络编程 dup和dup2函数
dup和dup2也是两个很实用的调用,它们的作用都是用来复制一个文件的描写叙述符. 它们经经常使用来重定向进程的stdin.stdout和stderr.这两个函数的原形例如以下: #include & ...
- 【APUE】第3章 文件I/O (3) 文件共享、原子操作、函数dup/dup2、函数sync/fsync/fdatasync、函数fcntl、函数ioct1、目录/dev/fd 使用说明
1.文件共享 UNIX系统支持在不同的进程间共享打开文件.为了说明这种共享,以下介绍内核用于所有I/O的数据结构. 内核使用3种数据结构表示打开文件,它们之间的关系决定了在文件共享方面一个进程对另一个 ...
- dup和dup2函数简单使用
dup函数 头文件和函数原型: #include <unistd.h> int dup(int oldfd); dup函数是用来打开一个新的文件描述符,指向和oldfd同一个文件,共享文件 ...
- [APUE]不用fcntl实现dup2函数功能
dup2的函数定义为: #include <unistd.h> int dup2(int src_fd, int new_fd); 自己实现dup2函数有几个关键点: 1,检查给定的源fd ...
随机推荐
- 自学Python6.4-内置模块(2)
自学Python之路-Python基础+模块+面向对象自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django 自学Pyth ...
- 【转】安全加密(二):BLE安全攻击反制措施
本文导读 近年来出现了越来越多的低功耗蓝牙应用,即BLE(Bluetooth Low Energy),比如说智能手环.防丢器等,对蓝牙的安全要求也越来越高.这篇文章将深入浅出说明BLE4.0~4.2中 ...
- numpy 从入门到遗忘
不常用的函数总是遗忘,很是困扰啊.于是痛下时间,做一个系统的总结,纯原创,都是些实际项目中常用的函数和方法,当然还有一些这边也是没有记录的,因为我在实际数据处理过程中也没有遇到过(如字符串处理等等). ...
- 洛谷P3230 比赛
emmmmmm,这个之前讲课的原题居然出到比赛里了. 我怒肝2h+然后A了此题,结果还是被某高一巨佬吊打...... 题意:n个球队两两比赛,胜得3分,败得0分,平得1分. 现有一个总分表,求问可能的 ...
- 洛谷 P1282 多米诺骨牌("01"背包)
传送门 https://www.cnblogs.com/violet-acmer/p/9852294.html 参考资料: [1]:https://blog.csdn.net/Darost/artic ...
- springmvc 中@Controller和@RestController的区别
@Controller和@RestController的区别? 官方文档:@RestController is a stereotype annotation that combines @Respo ...
- Database in BioInformation
很多数据库都可以通过下面的网站下载:http://annovar.openbioinformatics.org/en/latest/user-guide/download/ 一.NHLBI-ESP(E ...
- Python基础【day03】:字典(一)
本节内容 简述 语法 字典的使用 字典内置方法 一.简述 字典是Python中的又一种数据结构,它是通过key-value的数据类型,跟我们小时候用的新华字典差不多,通过key去访问value 二.语 ...
- 客户端连接linux经常间隔性断开链接【转】
起因 在使用SecureCRT通过telnet或SSH访问linux时,总是出现过段时间操作就会断开连接提示重连的问题.起初以为是网络不稳定造成的,但我测试发现在服务器端一直可以ping通客户端IP, ...
- python 创建实例--待完善
今天好好琢磨一下 python 创建实例的先后顺序 一. 就定义一个普通类 Util (默认)继承自 object,覆写 new ,init 方法 class Util(object): def __ ...