高級I/O模型(2)--dup/dup2

dup和dup2是兩個非常有用的調用,它們的作用都是用來複制一個文件的描述符。它們經常用來重定向進程的stdin、stdout和stderr。

這兩個函數的原形如下:

這裏寫圖片描述

利用函數dup,我們可以複製一個描述符。
傳給該函數一個既有的描述符,它就會返回一個新的描述符,這個新的描述符是傳給它的描述符的拷貝。這意味着,這兩個描述符共享同一個數據結構。

下面是用來說明dup函數使用方法的代碼片段:

 int fd1, fd2;
    ...
  fd2 = dup( fd1 );

下面簡單介紹一個的示例代碼:

//在文件log裏打印十次hello world
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>

int main()
{ 
    //close(1);
    int fd = open("./log", O_WRONLY|O_CREAT, 0644);
    if(fd < 0)
    { 
        perror("open\n");
        return 1;
    }
    close(1);
    fd = dup(fd);
    int count = 0;
    while(count++ < 10)
    { 
        printf("hello world!\n");
        fflush(stdout);
    }
    close(fd);
    return 0;
}

運行結果:
運行結果:
這裏寫圖片描述

需要注意的是,我們可以在調用fork之前建立一個描述符,這與調用dup建立描述符的效果是一樣的,子進程也同樣會收到一個複製出來的描述符。

dup2函數跟dup函數相似,但dup2函數允許調用者規定一個有效描述符和目標描述符的id。
dup2函數成功返回時,目標描述符(dup2函數的第二個參數)將變成源描述符(dup2函數的第一個參數)的複製品,換句話說,兩個文件描述符現在都指向同一個文件,並且是函數第一個參數指向的文件。

下面我們用一段代碼加以說明:

    int  oldfd;
    oldfd = open("./log",(O_WRONLY | O_CREATE), 0644 );
    dup2( oldfd, 1 );
    close( oldfd );

本例中,我們打開了一個當前目錄下的一個新文件,稱爲“log”,並收到一個文件描述符,該描述符叫做fd1。

我們調用dup2函數,參數爲oldfd和1,這會導致用我們新打開的文件描述符替換掉由1代表的文件描述符(即stdout,因爲標準輸出文件的id爲1)。
任何寫到stdout的東西,現在都將改爲寫入名爲“log”的文件中。

下面簡單介紹一個的示例代碼:

//在文件log裏打印十次hello world
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>

int main()
{ 
    umask(0);
    int fd = open("./log", O_WRONLY|O_CREAT, 0644);
    if(fd < 0)
    { 
        perror("open");
        return 1;
    }
    close(1);
    int ret = dup2(fd, 1);
    int count = 0;
    while(count++ < 10)
    { 
        printf("hello world!\n");
        fflush(stdout);
    }
    close(fd);
    return 0;
}

運行結果:
這裏寫圖片描述

需要注意的是,dup2函數在複製了oldfd之後,會立即將其關閉,但不會關掉新近打開的文件描述符,因爲文件描述符1現在也指向它。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章