美妙的檔案描述符傳遞

2021-04-12 16:42:01 字數 2294 閱讀 9282

我們知道父程序在子程序被fork出來之前開啟的檔案描述符是能被子程序繼承下來的,但是一旦子程序已經建立後,父程序開啟的檔案描述符要怎樣才能傳遞給子程序呢?unix提供相應的技術來滿足這一需求,這就是同一臺主機上程序間的檔案描述符傳遞,很美妙而且強大的技術。

想象一下我們試圖實現乙個伺服器,接收多個客戶端的連線,我們欲採用多個子程序併發的形式來處理多客戶端的同時連線,這時候我們可能有兩種想法:

1、客戶端每建立一條連線,我們fork出乙個子程序負責處理該連線;

2、預先建立乙個程序池,客戶端每建立一條鏈結,伺服器就從該池中選出乙個空閒(idle)子程序來處理該連線。

後者顯然更高效,因為減少了子程序建立的效能損耗,反應的及時性大大增強。這裡恰恰就出現了我們前面提到的問題,所有子程序都是在伺服器listen到一條連線以前就已經fork出來了,也就是說新的連線描述符子程序是不知道的,需要父程序傳遞給它,它接收到相應的連線描述符後,才能與相應的客戶端進行通訊處理。這裡我們就可以使用'傳遞檔案描述符'的方式來實現。

在'unix網路程式設計第1卷'的14.7小節中對這種技術有詳細的闡述,實際上這種技術就是利用sendmsg和recvmsg在一定的unix域套介面(或者是某種管道)上傳送和接收一種特殊的訊息,這種訊息可以承載'檔案描述符'罷了,當然作業系統核心對這種訊息作了特殊的處理。在具體一點兒'檔案描述符'是作為輔助資料(ancillary data)通過msghdr結構中的成員msg_control(老版本中稱為msg_accrights)傳送和接收的。值得一提的是傳送程序在將'檔案描述符'傳送出去後,即使立即關閉該檔案描述符,該檔案描述符對應的檔案裝置也沒有被真正的關閉,其引用計數仍然大於一,直到接收程序成功接收後,再關閉該檔案描述符,如果這時檔案裝置的引用計數為0,那麼才真正關閉該檔案裝置。

ok,下面是乙個簡單的檔案描述符傳遞的例子,該例子實現這樣乙個功能:即子程序負責在父程序傳遞給它的檔案描述符對應的檔案尾加上特定的'logo'字串。例子環境為solaris 9 + gcc 3.2

/* test_fdpass.c */

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include /* for socketpair */

#define my_logo         "-- tony bai"

static int send_fd(int fd, int fd_to_send)

else

msg.msg_name    = null;

msg.msg_namelen = 0;

iov[0].iov_base = buf;

iov[0].iov_len  = 1;

msg.msg_iov     = iov;

msg.msg_iovlen  = 1;

if(sendmsg(fd, &msg, 0) < 0)

return 0;

}static int recv_fd(int fd, int *fd_to_recv)

if(msg.msg_accrightslen != sizeof(int))

return 0;

}int x_sock_set_block(int sock, int on)

else

if (rv)

return 0;

}int main()

pid = fork();

if (pid == 0)

rv = recv_fd(sockpair[0], &fd);

if (rv < 0)

if (fd < 0)

exit(0);

}/* in parent */

for ( ; ; )

break;

}rv = send_fd(sockpair[1], fd);

if (rv != 0)

close(fd);

}wait(null);

return 0;

}編譯:gcc -o test_fdpass -lsocket -lnsl test_fdpass.c

執行:test_fdpass(事先在同一目錄下建立乙個檔案kk.log)

你可以發現kk.log內容的末尾已經加上了我的獨特logo '-- tony bai'。^_^

關於檔案描述符傳遞的更多細節, w. richard stevens的'unix網路程式設計第1卷'和'unix環境高階程式設計'兩本書中都有詳細說明,參讀即可。 

mysql 檔案描述符 檔案描述符

toc 首先,linux的世界裡一切皆為檔案,無論是裝置還是乙個socket連線。檔案又可分為 普通檔案 目錄檔案 鏈結檔案和裝置檔案。檔案描述符 file descriptor 是核心為了高效管理已被開啟的檔案所建立的索引,其是乙個非負整數 通常是小整數 用於指代被開啟的檔案,所有執行i o操作的...

檔案描述符

檔案描述符 是個很小的正整數,它是乙個索引值,指向核心為每乙個程序所維護的該程序開啟檔案的記錄表。檔案描述符的優點 相容posix標準,許多 linux 和unix 系統呼叫都依賴於它。檔案描述符的缺點 不能移植到unix以外的系統上去,也不直觀。基於檔案描述符的輸入輸出函式 open 開啟乙個檔案...

檔案描述符

作業系統程序表中存放各個檔案進行檔案描述 核心 kernel 利用檔案描述符 file descriptor 來訪問檔案。檔案描述符是非負整數。開啟現存盤案或新建檔案時,核心會返回乙個檔案描述符。讀寫檔案也需要使用檔案描述符來指定待讀寫的檔案。目錄檔案描述符概述 如何建立檔案描述符 使用的好處 缺點...