**:
我們知道父程序在子程序被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)
/* 處理fd描述符對應的檔案 */
rv = write(fd, my_logo, strlen(my_logo));
if (rv < 0) else
close(fd);
}exit(0);
}/* in parent */
for ( ; ; )
break;
}if (fd < 0)
printf("[parent]: open file error, errno is %d\n", errno);
}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)
[parent]: please enter filename:
kk.log
[parent]: please enter filename:
cc.log
[parent]: can't find file 'cc.log'
exit
[child]: child process exit normally!
你可以發現kk.log內容的末尾已經加上了我的獨特logo '-- tony bai'。^_^
關於檔案描述符傳遞的更多細節, w. richard stevens的'unix網路程式設計第1卷'和'unix環境高階程式設計'兩本書中都有詳細說明,參讀即可。
程序間SOCKET控制代碼傳遞 程序池應用
1。函式及結構介紹 開發通訊程式,經常遇到服務程式的開發,常見使用程序池及執行緒池,下面介紹一對在程序池應用非常有用的函式,sendmsg recvmsg,可以通過這組函式在程序中傳遞socket描述符。可以在主程序使用多路復用偵聽socket事件,將讀寫事件控制代碼傳遞給工作程序進行處理。在使用函...
Socket程序間通訊
int socket int domain,int type,int protocol int bind int sockfd,const struct sockaddr addr,socklen t addrlen struct sockaddr in internet address.struc...
程序間傳遞訊息
使用自定義訊息 1 首先定義訊息 例如 define wm yourmesg wm user 100 2 加入訊息響應巨集,在響應該訊息的類中 c c code?1 2 3 4 5 begin message map cchiliddlg,cdialog afx msg map end messag...