1. 程式人生 > >UNIX環境高階程式設計習題之第三章第二題

UNIX環境高階程式設計習題之第三章第二題

不呼叫fcntl函式實現dup2函式

問題描述

dup2函式頭定義為int dup2(int fd, int fd2),返回值為fd2指定的檔案描述符,指向fd指向的檔案,如果fd2已經開啟,則需先關閉;如果fd == fd2,則無需關閉fd2。

解題思路

1、尋找需要的檔案描述符
不能呼叫fcntl,那麼我們只能呼叫dup函式,這個函式會返回當前可用的檔案描述符中的最小值,迴圈n次呼叫直到返回值等於fd2。

2、呼叫dup的負面影響
這個時候我們打開了n-1個無用的檔案,這些並不是我們需要或者預期的,返回前需關閉。否則不但會佔用大量系統資源,使得系統無法開啟新的檔案,甚至這些預期之外的檔案描述符也可以訪問或者修改檔案,形成安全隱患。

3、消除dup造成的隱患
線性結構記錄n-1個檔案描述符,並依次關閉

4、錯誤error處理
dup呼叫錯誤:包括指定的fd2過大,開啟的檔案描述符超出限制。在不考慮其他程式也呼叫此函式的情況下,我們可以通過sysconf函式來獲取開啟上限。

5、測試問題
定義一個檔案描述符x指向標準輸出,並通過x寫入一段特定的字元,檢視是否會在標準輸出是列印,也可以直接重定向到指定檔案檢視。

程式碼實現

本文采用c語言實現該邏輯:

#include "apue.h"
#include <myerr.h>
#include <limits.h> #include <unistd.h> #include <errno.h> #ifdef OPEN_MAX static long openmax = OPEN_MAX; #else static long openmax = 0; #endif int mydup(int fd, int fd2){ //獲取系統允許的最大的檔案數 errno = 0; if (openmax == 0) openmax = sysconf(_SC_OPEN_MAX); if (openmax < 0
){ if (errno != 0){ //這個值是不確定的 printf("OPEN_MAX這個值是不確定的,設為預設100\n"); openmax = 100; } else{ //獲取OPEN_MAX錯誤 printf("獲取OPEN_MAX錯誤,設為預設100\n"); openmax = 100; } }else printf("OPEN_MAX獲取成功,其值是%ld\n", openmax); //關閉指定的fd2檔案 errno = close(fd2); //關閉檔案不一定會成功,因為有可能這個檔案本身就沒有開啟,所以錯誤也不退出 if (errno == -1) printf("關閉fd2錯誤:%d",errno); //獲取待返回的檔案描述符fd1 long fd1 = -1; int arr[openmax-1], idx = 0,i; for (i = 0; i < openmax - 1; i++){// 初始化線性結構 arr[i] = -1; } do{//迴圈呼叫dup函式直至返回的fd1 == fd2 fd1 = dup(fd); if (fd1 > 0){//呼叫成功 if (fd1 == fd2){//如果呼叫成功,退出迴圈 break; }else{ arr[idx] = fd1; idx++; } } }while(fd1 < fd2); //關閉開啟的多餘的檔案 for (i = 0; i < openmax - 1; i++){ if (arr[i] == -1) break; else{ errno = close(arr[i]); if (errno == -1){ printf("關閉檔案%ld錯誤",arr[i],stdout); if (idx != i){ idx = i; i--; //關閉失敗回退再關閉一次 } } } } return fd1; } int main(void){ int fdtest = dup(1); char buf[] = "hello, mydup for dup2!\n"; printf("開啟的檔案是:%d,buf長度是%d\n",fdtest,strlen(buf)); int fd = mydup(STDOUT_FIFLNO,fdtest); printf("mydup返回的檔案是:%d\n",fd); //測試返回的檔案符是否可以直接操作標準輸出 if (write(fd, buf, strlen(buf)) != strlen(buf)) err_sys("buf write error\n"); exit(0); }

在Linux環境下的執行結果如下:

開啟的檔案是:3,buf長度是23
OPEN_MAX獲取成功,其值是102400
mydup返回的檔案是:3
hello, mydup for dup2!

可見測試的buf成功通過獲取的檔案描述符寫入到了標準輸出中,至此測試完畢。