dup & dup2
轉: http://xgc94418297.blog.163.com/blog/static/112966040200922593724989/
轉: http://xgc94418297.blog.163.com/blog/static/112966040200922593724989/
dup和dup2也是两个非常有用的调用,它们的作用都是用来复制一个文件的描述符。它们经常用来重定向进程的stdin、stdout和stderr。这两个函数的原形如下:
#include <unistd.h>
int dup( int oldfd );
int dup2( int oldfd, int targetfd );
int dup2( int oldfd, int targetfd );
dup :
重定向标准输出到一个文件, 为当前进程关闭标准输出,并重新设置标准输出到一个pfd文件,并关闭原始的文件描述符
原型 : int dup(int file_desc);
作用: 复制一个和file_desc指向同一个文件的文件描述符, 并且新的文件描述符总是取最小的可用值。
这样一来就可有一个诀窍:因为标准输入描述符总是0,并且dup函数调用总是取最小可用的数字,如果关闭0,再调用dup函数,新的文件描述符就是0了。
(1). Example:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
int fd;
/* 读写方式打开一个文件, 没有就创建 */
/* 读写方式打开一个文件, 没有就创建 */
if ((fd = open("test",O_RDWR|O_CREAT))<0) {
perror("open error");
exit(1);
}
close(1); //先关闭stdout
dup(fd); //重定向到fd,也就是test文件中
//调用命令
//调用命令
if (execl("/bin/ls","ls","-al",NULL)<0) {
perror("error");
exit(1);
}
return 0;
}
执行的命令“ls -al”就会被重定向到文件test中 dup2 :
dup2函数跟dup函数相似,但dup2函数允许调用者规 定一个有效描述符和目标描述符的id。dup2函数成功返回时,目标描述符(dup2函数的第二个参数)将变成源描述符(dup2函数的第一个参数)的复 制品,换句话说,两个文件描述符现在都指向同一个文件,并且是函数第一个参数指向的文件。(还是不太明白)
利用函数dup,我们可以复制一个描述符。传给该函数一个既有的描述符,它就会返回一个新的描述符,这个新的描述符是传给它的描述符的拷贝。这意味着,这 两个描述符共享同一个数据结构。例如,如果我们对一个文件描述符执行lseek操作,得到的第一个文件的位置和第二个是一样的。
需要注意的是,我们可以在调用fork之前建立一个描述符,这与调用dup建立描述符的效果是一样的,子进程也同样会收到一个复制出来的描述符。
注意:dup函数会将打开的文件描述符重定向到当前进程最小的,未使用的描述符
由于关闭了标准输出,因此起就是标准输出的描述符。
利用函数dup,我们可以复制一个描述符。传给该函数一个既有的描述符,它就会返回一个新的描述符,这个新的描述符是传给它的描述符的拷贝。这意味着,这 两个描述符共享同一个数据结构。例如,如果我们对一个文件描述符执行lseek操作,得到的第一个文件的位置和第二个是一样的。
需要注意的是,我们可以在调用fork之前建立一个描述符,这与调用dup建立描述符的效果是一样的,子进程也同样会收到一个复制出来的描述符。
注意:dup函数会将打开的文件描述符重定向到当前进程最小的,未使用的描述符
由于关闭了标准输出,因此起就是标准输出的描述符。
(1). Example 1 -
用dup2实现: ls –al | more
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
int main()
{
int fd[2];
pid_t pid;
if ( pipe(fd)<0 )
{
perror("pipe error");
exit(1);
}
if ((pid=fork())<0 )
{
perror("fork error");
exit(1);
}
else if (pid == 0)
{
close(1);
dup2(fd[1],1);
close(fd[0]);
execlp("ls","ls","-al",NULL);
}
else
{
close(0);
dup2(fd[0],0);
close(fd[1]);
execlp("more","more",NULL);
}
return 0;
}
创建一个管道,程序有两个进程,一个子进程,一个父进程。
子进程中,先关闭stdout描述符,用dup2重定向到管道的输入端,关闭输出端,用execlp把子进程映像替换成ls –al,
父进程中,先关闭stdin描述符,就不从标准输入设备读取以,而从其他程序接收数据,用dup2重定向到管道的输出端,关闭输入端,用execlp,把父进程映像替换成more,more命令把管道的内容做为它的输入。
我们的子进程把它的输出重定向的管道的输入,然后,父进程将它的输入重定向到管道的输出。
(2). Example -
重定向錯誤輸出stderr到標準輸出stdout -- dup2(1, 2);
看看这段示范代码
(3). Example -
fprintf 和printf:printf是键盘和显示器终端输出,而fprintf是设备
(4). Example -
(2). Example -
重定向錯誤輸出stderr到標準輸出stdout -- dup2(1, 2);
看看这段示范代码
#include <stdio.h>
#include <unistd.h >
int main()
{
//dup2(1, 2);
fprintf(stdout, "stdout\n");
fprintf(stderr, "stderr\n");
return 0;
}
分别往stdout和stderr输出”stdout”, “stderr”, 看看运行结果$ ./r > 1.txt
stderr
$ cat 1.txt
stdout
显然是符合预期的, 我们把上面那段代码的dup2(1, 2) 启用,重新看看执行结果$ ./r > 2.txt
$ cat 2.txt
stderr
stdout
明显,就是stderr已经重定向到stdout了,内容都输出到stdout里面了(3). Example -
fprintf 和printf:printf是键盘和显示器终端输出,而fprintf是设备
#include <stdio.h>
#define err_quit printf
int main(int argc, char *argv[])
{
int fd;
if(argc!=2) {
err_quit("Usage :filename");
}
if((fd=creat(argv[1],0644))<0) {
err_quit("create file failed");
}
close(1);/*close the stdout,so can redirect to file*/
dup(fd);
close(fd);
printf("what are you thinking???\n");
FILE *fp;
fp = fopen("ceshi1.txt","w");
if(fp==NULL)
return ;
fprintf(fp,"%s\n","hello");
}
(4). Example -
#include <stdio.h>
#define err_quit printf
int main(int argc, char *argv[])
{
int fd,fd2, fd3, fd4;
FILE *fp2, *fp3, *fp4;
if(argc!=2) {
err_quit("Usage :filename");
}
if((fd=creat(argv[1],0644))<0) {
err_quit("create file failed");
}
//close(1);/*close the stdout,so can redirect to file*/
fd2 = dup(fd);
fd3 = dup(fd);
close(1);
fd4 = dup(fd2);
//close(1);
//dup(fd4);
printf("fd(%d), fd2(%d), fd3(%d), fd4(%d)", fd, fd2, fd3, fd4);
close(fd);
printf("what are you thinking???\n");
//FILE *fp;
//fp = fopen("ceshi1.txt","w");
//if(fp==NULL)
// return ;
//fprintf(fp,"%s\n","hello");
}int fd,fd2, fd3, fd4;
FILE *fp2, *fp3, *fp4;
if(argc!=2) {
err_quit("Usage :filename");
}
if((fd=creat(argv[1],0644))<0) {
err_quit("create file failed");
}
//close(1);/*close the stdout,so can redirect to file*/
fd2 = dup(fd);
fd3 = dup(fd);
close(1);
fd4 = dup(fd2);
//close(1);
//dup(fd4);
printf("fd(%d), fd2(%d), fd3(%d), fd4(%d)", fd, fd2, fd3, fd4);
close(fd);
printf("what are you thinking???\n");
//FILE *fp;
//fp = fopen("ceshi1.txt","w");
//if(fp==NULL)
// return ;
//fprintf(fp,"%s\n","hello");
No comments:
Post a Comment