dup和dup2

閱讀一些C或者C++第三方庫開源源碼的時候,有些源碼中會使用dup和dup2這兩個函數,由於在工作中基本上用不到這兩個函數,所以它們對閱讀源代碼提升了一些難度。雖然當時看過相關博文後能理解,不過過了一段時間就又忘了,今天不算總結,就把這兩個函數的經典特性給blog出來。

先看一下dup和dup2函數的原型:

#include<unistd.h>
int dup(int fd);
int dup2(int fd1,int fd2);
兩個均爲複製一個現存的文件的描述
兩個函數的返回:若成功爲新的文件描述,若出錯爲-1;
由dup返回的新文件描述符一定是當前可用文件描述中的最小數值。
用dup2則可以用fd2參數指定新的描述符數值。
如果fd2已經打開,則先關閉。若fd1=fd2,則dup2返回fd2,而不關閉它。
通常使用這兩個系統調用來重定向一個打開的文件描述符。

我看完這一段話之後,感覺非常抽象,還是用一個例子說明吧。

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

int main(int argc, char** argv)
{
	int fd = open("./test.conf", O_RDWR | O_CREAT);
	printf("fd: %d\n", fd);
	close(1);
	dup(fd);
	printf("ma52103231\n");
}
從這段代碼中可以看到,先用open打開文件。爲什麼是open而不是fopen?因爲dup和dup2的參數是文件描述符而不是fopen返回的FILE*指針。

然後使用printf打印出fd的值。接着使用close關閉文件描述符1(1當前指代這標準輸出),關閉的意思就是解綁,把1和標準輸出解除綁定,之後對1的操作再也影響不到標準輸出了,而1處於空閒狀態。在之後使用dup(fd)來duplicate參數fd。這在系統內部執行了一個查詢操作。內部會尋找當前可用的最小空閒文件描述符,由於1已經處於空閒狀態,所以1也指向了fd指向的test.conf文件,而test.conf文件的引用計數加一。最後使用printf輸出語句,由於printf默認將語句輸出到文件描述符1,所以看如下內容:

root@hu-virtual-machine:/home/hu/project/c_# gcc main.c -o myexpect
root@hu-virtual-machine:/home/hu/project/c_# ./myexpect 
fd: 3
root@hu-virtual-machine:/home/hu/project/c_# cat test.conf 
ma52103231
root@hu-virtual-machine:/home/hu/project/c_# 
從上可以看到,“ma52103231”被printf寫入到了文件中。同時注意到fd的值爲3,說明,一個程序在運行時,文件描述符0,1,2默認已經打開,這個時候空閒的最小文件描述符是3.

再來看dup2,依然通過一個例子:

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

int main(int argc, char** argv)
{
	int fd = open("./test.conf", O_RDWR | O_CREAT);
	printf("fd: %d\n", fd);
	close(1);
	dup(fd);

	dup2(fd, 2);
	fprintf(stdout, "ma52103231\n");
	fprintf(stderr, "this is a error\n");
	
}
我們知道文件描述符2指代標準錯誤,通過dup2函數,將fd duplicate到文件描述符2,不過在此之前,先close調文件描述符2,所以代碼中沒有出現close(2這個語句),因爲dup2函數已經幫我們做了這一步。程序最後通過fprintf函數將內容寫到第一個參數指定的目標中去的特性,實現寫文件,看一下文件內容:
root@hu-virtual-machine:/home/hu/project/c_# cat test.conf 
ma52103231
this is a error

以上就是dup和dup2兩個函數的使用小例子。再使用兩個函數的過程中,要清楚的明白,它們在執行時會執行一個尋找操作,尋找當前程序中最小的處於空閒狀態的文件描述符,而一般來說close函數會使一個描述符變成空閒(假若一個描述符的引用計數很多,調用一次close並不會使這個描述符空閒,所以是一般來說,不過在使用dup和dup2的場景中,這樣的情況我是很少看到),所以dup和close經常成對出現。而對於dup2,一定要記住,它內部有個close操作。



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