← 返回首页
Linux高级程序设计(五十一)
发表时间:2021-12-04 00:07:49
dup和dup2函数

dup和dup2函数用来复制一个现存的文件描述符。

1.dup函数

#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);

当调用dup函数时,内核在进程中创建一个新的文件描述符,此描述符是当前可用文件描述符的最小数值,这个文件描述符指向oldfd所拥有的文件表项。

实际上,调用dup(oldfd)等效于,fcntl(oldfd, F_DUPFD, 0);

实例:

使用dup实现输出到控制台。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>

int main(int argc, char const *argv[])
{
    /* code */
    int fd;
    fd = dup(1);
    printf("fd=%d\n",fd);
    write(fd,"hello,world!\n",strlen("hello,world!\n"));

    return 0;
}

运行结果:

[root@iz2zefozq9h39txdb8s7npz shelldemo]# ./a.out
fd=3
hello,world!

dup实现类似输出重定向的功能。例如:

[root@iz2zefozq9h39txdb8s7npz shelldemo]# echo 'hello,world!' > haha.txt
[root@iz2zefozq9h39txdb8s7npz shelldemo]# cat haha.txt
hello,world!
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>

int main(int argc, char const *argv[])
{
    /* code */
    int fd;
    int fd_file;
    fd_file = open("haha.txt",O_WRONLY|O_CREAT|O_TRUNC,0664);
    if(fd_file==-1){
        perror("error to open file:");
        exit(1);
    }

    close(1); //关闭默认输出的文件描述符
    fd = dup(fd_file);
    printf("welcome to linux world!\n");
    printf("fd=%d\n",fd);

    return 0;
}

运行结果:

[root@iz2zefozq9h39txdb8s7npz shelldemo]# gcc test_dup.c
[root@iz2zefozq9h39txdb8s7npz shelldemo]# ./a.out
[root@iz2zefozq9h39txdb8s7npz shelldemo]# cat haha.txt
welcome to linux world!
fd=1

输出重定向后如何恢复回来?

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>

int main(int argc, char const *argv[])
{
    /* code */
    int fd1;
    int fd2;

    fd2 = dup(1);
    printf("fd2=%d\n",fd2);

    fd1 = open("haha.txt",O_RDWR|O_TRUNC,0664);

    close(1); //关闭默认输出的文件描述符

    int fd3 = dup(fd1);
    printf("welcome to linux world!\n");
    printf("fd3=%d\n",fd3);


    close(1);

    int fd4 = dup(fd2);
    printf("welcome to java world!\n");
    printf("fd4=%d\n",fd4);

    return 0;
}

运行结果:

[root@iz2zefozq9h39txdb8s7npz shelldemo]# ./a.out
fd2=3
welcome to java world!
fd4=1
[root@iz2zefozq9h39txdb8s7npz shelldemo]# cat haha.txt
welcome to linux world!
fd3=1

2.dup2函数

dup2和dup的区别就是可以用newfd参数指定新描述符的数值,如果newfd已经打开,则先将其关闭。如果newfd等于oldfd,则dup2返回newfd, 而不关闭它。dup2函数返回的新文件描述符同样与参数oldfd共享同一文件表项。

调用dup2(oldfd, newfd)等效于,close(oldfd);fcntl(oldfd, F_DUPFD, newfd);

实例:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>

int main(int argc, char const *argv[])
{
    /* code */
    int fd1;
    int fd2;
    fd1=open("haha.txt",O_CREAT|O_WRONLY,0664);

    if(fd1<0){
        perror("error to open file:");
        exit(1);
    }
    //首先关闭1文件描述符,在把fd1复制给1,意味着1和fd1都标识haha.txt文件
    fd2 = dup2(fd1,1);
    printf("hello,world!\n");
    printf("fd2=%d\n",fd2);

    return 0;
}

运行结果:

[root@iz2zefozq9h39txdb8s7npz shelldemo]# ./a.out
[root@iz2zefozq9h39txdb8s7npz shelldemo]# cat haha.txt
hello,world!
fd2=1

输出重定向后如何恢复回来?

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>

int main(int argc, char const *argv[])
{
    /* code */
    int fd1;
    int fd2=3;
    //将1文件描述符复制给fd2,所以fd2就标识标准输出流。
    dup2(1,fd2);
    printf("fd2=%d\n",fd2);

    fd1=open("haha.txt", O_CREAT|O_WRONLY,0664);
    if(fd1<0){
        perror("error to open file:");
        exit(1);
    }

    //关闭文件描述符1,将fd1复制给1,所以1文件描述符标识haha.txt
    dup2(fd1,1);
    printf("hello,world!\n");


    dup2(fd2,1);
    printf("welcome to linux world!\n");

    return 0;
}

运行结果:

[root@iz2zefozq9h39txdb8s7npz shelldemo]# ./a.out
fd2=3
welcome to linux world!
[root@iz2zefozq9h39txdb8s7npz shelldemo]# cat haha.txt
hello,world!