Linux 程序間傳遞檔案描述符

2022-09-09 19:12:22 字數 2839 閱讀 3205

程序間傳遞開啟的檔案描述符,並不是傳遞檔案描述符的值。先說一下檔案描述符。

對核心來說,所有開啟的檔案都會通過檔案描述符引用,檔案描述符在程序中是乙個非負整數,檔案描述符在程序中是從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...