天天看點

九、dup(duplicate)和dup2函數九、dup(duplicate)和dup2函數

九、dup(duplicate)和dup2函數

目錄:

  • 九、dup(duplicate)和dup2函數
        • 一、重定向
        • 二、dup()函數原型
    • int dup(int oldfd);
        • 三、dup2()函數原型
    • int dup2(int oldfd, int newfd);
        • 四、fcntl()函數實作dup()和dup2()
    • int new_fd = fcntl(int old_fd, int cmd, int fd_no);

一、重定向

現假設有一打開的檔案,該檔案描述符為

old_fd

現建立另一個新的檔案描述符

new_fd

,該檔案描述符不指向任何檔案,現使

new_fd

重定向于

old_fd

,則檔案描述符

new_fd

就會指向

old_fd

所描述的檔案,這就是重定向;

最終,相當于

new_fd

old_fd

指向同一檔案(最初

old_fd

所指向的檔案),如圖所示:

九、dup(duplicate)和dup2函數九、dup(duplicate)和dup2函數

當然,即使

new_fd

已指向某一檔案,也可以用于重定向

二、dup()函數原型

包含頭檔案:

int dup(int oldfd);

建立一個新的檔案描述符,将新的檔案描述符定向到

oldfd

所描述的檔案,新的檔案描述符序号将是編号最低的未使用的檔案描述符

int oldfd

已有的檔案描述符,即重定向目标檔案的檔案描述符,可以是

STDIN_FILENO

STDOUT_FILENO

STDERR_FILENO

傳回值

成功時傳回一個新的檔案描述符,失敗傳回 -1,errno,新的檔案描述符序号将是編号最低的未使用的檔案描述符

例如:使用重定向的檔案描述符向檔案寫入内容

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
    int old_fd = open(argv[1], O_RDWR | O_APPEND);
    if(fd == -1)
    {
        perror("open error");
        exit(1);
    }

    int new_fd = dup(old_fd);
    if(new_fd == -1)
    {
        perror("dup error");
        exit(1);
    }

    printf("new_fd = %d\n", new_fd);

    int ret = write(new_fd, "Hello World!\n", 13);
    if(ret == -1)
    {
        perror("write error");
        exit(1);
    }

    return 0;
}
           

打開檔案後,

old_fd

值為 3,則

new_fd

将是編号最低的未使用的檔案描述符,即

new_fd

值為 4

九、dup(duplicate)和dup2函數九、dup(duplicate)和dup2函數

三、dup2()函數原型

包含頭檔案:

int dup2(int oldfd, int newfd);

newfd

檔案描述符重定向到

oldfd

所描述的檔案

int oldfd

已有的檔案描述符,即重定向目标檔案的檔案描述符,可以是

STDIN_FILENO

STDOUT_FILENO

STDERR_FILENO

int newfd

重定向的檔案描述符

傳回值

失敗時傳回 -1、errno

dup()

不同的是,

dup()

所建立的新的檔案描述符的編号将是編号最低的未使用的檔案描述符,而

dup2()

則可以由使用者指定 newfd,如圖所示:

九、dup(duplicate)和dup2函數九、dup(duplicate)和dup2函數

相當于:

九、dup(duplicate)和dup2函數九、dup(duplicate)和dup2函數

例如:使用

dup2()

把本來要列印到螢幕上的内容輸出到指定檔案,需要用到标準輸出檔案的宏

STDOUT_FILENO

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
    int fd = open(argv[1], O_RDWR | O_APPEND);
    if(fd == -1)
    {
        perror("open error");
        exit(1);
    }

	// 将标準輸出檔案的檔案描述符重定向于 fd 所描述的檔案
    int ret = dup2(fd, STDOUT_FILENO);
    if(ret == -1)
    {
        perror("dup2 error");
        exit(1);
    }

	// 向螢幕輸出内容
    printf("Hello World!\n");

    return 0;
}
           
九、dup(duplicate)和dup2函數九、dup(duplicate)和dup2函數

原理圖:

九、dup(duplicate)和dup2函數九、dup(duplicate)和dup2函數

四、fcntl()函數實作dup()和dup2()

int new_fd = fcntl(int old_fd, int cmd, int fd_no);

使用

fcntl()

函數實作

dup()

dup2()

的功能

int old_fd

已存在的檔案描述符

int cmd

該參數應選擇

F_DUPFD

int fd_no

指定

new_fd

的檔案描述符;若檔案描述符被占用,則

new_fd

的編号将設為 >=

int fd_no

的未使用的檔案描述符;若檔案描述符未被使用,則

new_fd

的編号将設為

fd_no

所指定的編号

傳回值

成功時傳回

new_fd

的檔案描述符,失敗時傳回 -1、errno

例如:檢驗

fcntl()

的dup功能

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
    int old_fd = open(argv[1], O_RDWR);
    if(old_fd == -1)
    {
        perror("open error");
        exit(1);
    }

    // 檔案描述符0被占用,new_fd1 将被指定為編号最低的未使用的檔案描述符,即 4
    int new_fd1 = fcntl(new_fd1, F_DUPFD, 0);
    if(new_fd1 == -1)
    {
        perror("fcntl error");
        exit(1);
    }
    printf("new_fd1 = %d\n", new_fd1);

    // 檔案描述符10未被使用,new_fd2 将被指定為 10
    int new_fd2 = fcntl(new_fd2, F_DUPFD, 10);
    if(new_fd2 == -1)
    {
        perror("fcntl error");
        exit(1);
    }
    printf("new_fd2 = %d\n", new_fd2);

    return 0;
}
           
九、dup(duplicate)和dup2函數九、dup(duplicate)和dup2函數

繼續閱讀