程序間傳遞開啟的檔案描述符,並不是傳遞檔案描述符的值。先說一下檔案描述符。
對核心來說,所有開啟的檔案都會通過檔案描述符引用,檔案描述符在程序中是乙個非負整數,檔案描述符在程序中是從0開始,預設0與標準輸入關聯、1與標準輸出關聯、2與標準出錯關聯。之後程序每開啟乙個檔案或者建立乙個新檔案的時候,核心都會向程序返回乙個檔案描述符來表示這個檔案,檔案描述符是遞增的。檔案描述符的值與檔案沒有必然的聯絡,只是該檔案在程序中的乙個標識,所以同一檔案在不同程序中的檔案描述符可能不一樣,相同值得檔案描述符在不同程序中可能標識不同得檔案。檔案描述符的取值範圍是0~open_max。
接下來要明白檔案共享涉及的資料結構。
核心使用三種資料結構來表示開啟的檔案:
三者的關係如下:
在程序間傳遞檔案描述符是非常有用的,通過傳遞檔案描述符,可以讓其他程序擁有對檔案操作的能力,在網路程式設計中體現比較多,比如nobody程序協助建立了資料連線,然後將socket的檔案描述符傳遞給服務程序,由服務程序進行資料傳輸。
這是兩個程序分別開啟同一檔案的情況:
這是程序共享檔案描述符的狀態·:
所以共享檔案描述符就是將不同檔案描述符指向乙個檔案表。這一點與fork產生的父子程序共享已開啟的檔案描述符是一樣的。還要注意,一般檔案在關閉檔案描述符之後就關閉檔案了,但是共享檔案的情況不一樣,共享檔案要等到所有引用的檔案描述符關閉之後才可關閉。
可以通過unix域socket來傳遞檔案描述符,實際是呼叫了socket中的sendmsg和recvmsg函式,利用sendmsg和recvmsg可以傳送附屬資料,附屬資料可以是是檔案描述符,兩個函式的原型如下:
ssize_t sendmsg
(int sockfd,
const
struct msghdr *msg,
int flags)
;ssize_t recvmsg
(int sockfd,
struct msghdr *msg,
int flags)
;struct msghdr
;//套介面位址成員msg_name與msg_namelen。
//i/o向量引用msg_iov與msg_iovlen。
//附屬資料緩衝區成員msg_control與msg_controllen。
//接收資訊標記位msg_flags。
其中,對於傳遞檔案描述符有用的成員為:msg_control和msg_controllen,需要注意的是,如果想利用它傳遞輔助資訊,比如檔案描述符,必須攜帶至少乙個位元組的真實資料,也就是iov指標指向的緩衝區要有資料,iovlen至少是1。
傳遞附屬資料cmsghdr的結構如下:
struct cmsghdr
;
首先要明白什麼是附屬資料,recvmsg與sendmsg函式允許程式傳送或是接收附屬資料,這些額外的資訊受限於一定的格式規則,也就是控制資訊頭與管理這些資訊的巨集。
為了傳送檔案描述符,將cmsghdr中的成員設定如下:
緊隨cmsg_type 之後的存放內容,就是描述符。通過cmsg_data獲取整型量的指標。
如何將檔案描述符傳遞放在附屬資料中傳送呢?如下:
//附屬資料的配置
p_cmsg =
cmsg_firsthdr
(&msg)
;//返回附屬資料部分的第乙個cmsghdr
p_cmsg->cmsg_level = sol_socket;
p_cmsg->cmsg_type = scm_rights;
p_cmsg->cmsg_len =
cmsg_len
(sizeof
(fd));
//返回附屬資料長度
int*p_fds;
p_fds =
(int*)
cmsg_data
(p_cmsg)
;*p_fds = fd;
//設定待傳送的檔案描述符 將fd儲存在淨荷資料位址
這些巨集定義的作用如下:
#define cmsg_align(len) ( ((len)+sizeof(long)-1) & ~(sizeof(long)-1) )
為了建立輔助資料,首先初始化msghdr.msg_controllen欄位。 在msghdr上使用cmsg_firsthdr()
來獲取第乙個控制訊息,然後使用cmsg_nxthdr()
來獲取後續的控制訊息。在每乙個控制訊息中,使用cmsg_len()
來初始化cmsghdr.cmsg_len,使用cmsg_data()
來初始化cmsghdr.cmsg_data部分
參考:所以傳送檔案描述符的**如下:
void
send_fd
(int sock_fd,
int fd)
在接收檔案描述符的時候:
int
recv_fd
(const
int sock_fd)
Linux 程序間傳遞檔案描述符
程序間傳遞開啟的檔案描述符,並不是傳遞檔案描述符的值。先說一下檔案描述符。對核心來說,所有開啟的檔案都會通過檔案描述符引用,檔案描述符在程序中是乙個非負整數,檔案描述符在程序中是從0開始,預設0與標準輸入關聯 1與標準輸出關聯 2與標準出錯關聯。之後程序每開啟乙個檔案或者建立乙個新檔案的時候,核心都...
Linux下程序間傳遞描述符
linux下程序間傳遞描述符 每個程序都有自己的程序空間,這使得描述符在程序間傳遞變得不容易。就比如說linux下提供程序間傳遞描述符的機制,但是卻要求兩個程序是父子程序。linux程序間傳遞描述符的機制是通過sendmsg和recvmsg兩個函式實現的 該機制可以傳遞任意形式的描述符,如pipe ...
android程序間傳遞檔案描述符原理
在linux中,程序開啟乙個檔案,返回乙個整數的檔案描述符,然後就可以在這個檔案描述符上對該檔案進行操作。那麼檔案描述符和檔案到底是什麼關係?程序使用的是虛擬位址,不同程序間是位址隔離的,如何在兩個程序中傳遞檔案描述符,然後指向同一檔案 binder傳遞檔案描述符 核心中每個程序都使用task st...