struct msghdr以及iovec介紹

2021-10-07 05:23:41 字數 3313 閱讀 9572

結構體原型

#include

struct msghdr

;ssize_t recvmsg (

int sockfd ,

struct msghdr * msg ,

int flags )

; ssize_t sendmsg (

int sockfd ,

struct msghdr * msg ,

int flags )

;成功時候返回讀寫位元組數,出錯時候返回-

1.

這2個函式只用於套介面,不能用於普通的i/o讀寫,引數sockfd則是指明要讀寫的套介面。

flags用於傳入控制資訊,一般包括以下幾個

msg_dontroute send可用

msg_donwait send與recv都可用

msg_peek recv可用

msg_waitall recv可用

msg_oob send可用

msg_eor send recv可用

返回資訊都記錄在struct msghdr * msg中

msg_name是指向乙個結構體struct sockaddr的指標

msg.msg_name = ;

msg.msg_namelen = 16;長度一半設定為16

多緩衝區的傳送和接收處理就是乙個struct iovec的陣列,每個成員的io_base都指向了不同的buffer的位址。io_len是指該buffer中的資料長度。而在struct msghdr中的msg_iovlen是指buffer緩衝區的個數,即iovec陣列的長度。

msg_control欄位的也是指向一段記憶體,msg_controllen是指該記憶體的總大小長度,通常該記憶體被用來儲存輔助資料,輔助資料可用於一些特殊的處理。msg_control通常指向乙個控制訊息頭部,其結構體如下所示:

struct cmsghdr  

;

iovec結構體定義及使用

readv(2)與writev(2)函式都使用乙個i/o向量的概念。這是由所包含的檔案定義的:

#include

標頭檔案定義了struct iovc,其定義如下:

struct iovec 

;

struct iovec定義了乙個向量元素。通常,這個結構用作乙個多元素的陣列。對於每乙個傳輸的元素,指標成員iov_base指向乙個緩衝區,這個緩衝區是存放的是readv所接收的資料或是writev將要傳送的資料。成員iov_len在各種情況下分別確定了接收的最大長度以及實際寫入的長度。

int readv(int fd, const struct iovec *vector, int count);

int writev(int fd, const struct iovec *vector, int count);

這些函式需要三個引數:

要在其上進行讀或是寫的檔案描述符fd

讀或寫所用的i/o向量(vector)

要使用的向量元素個數(count)

這些函式的返回值是readv所讀取的位元組數或是writev所寫入的位元組數。如果有錯誤發生,就會返回-1,而errno存有錯誤**。注意,也其他i/o函式類似,可以返回錯誤碼eintr來表明他被乙個訊號所中斷。

我們從乙個實際的資料報傳送的例子入手,來看看其傳送的具體流程,以及過程中涉及到的相關資料結構。在我們的虛擬機器上傳送icmp回顯請求包,ping另一台主機172.16.48.1.我們使用系統呼叫sendto傳送這個icmp包

ssize_t sendto

(int s,

const

void

*buf, size_t len,

int flags,

const

struct sockaddr *to, socklen_t tolen)

;

系統呼叫sendto最終呼叫核心函式

asmlinkage long

sys_sendto

(int fd,

void __user *buff, size_t len,

unsigned flags,

struct sockaddr __user *addr,

int addr_len)

sys_sendto構建乙個結構體struct msghdr,用於接收來自應用層的資料報,下面是結構體struct msghdr的定義:

struct msghdr 

;

這個結構體的內容可以分為四組:

(1) 第一組是msg_name和msg_namelen,記錄這個訊息的名字,其實就是資料報的目的位址。

msg_name是指向乙個結構體struct sockaddr的指標。長度為16:

struct sockaddr
所以,msg_namelen的長度為16.需要注意的是,結構體struct sockaddr只在進行引數傳遞時使用,無論是在使用者態還是在核心態,我們把其強制轉化為結構體struct sockaddr_in:

struct sockaddr_in 

;struct in_addr

msg.msg_namelen=

16

請求回顯icmp包沒有目的端位址的埠號。

(2) 第二組是msg_iov和msg_iovlen,記錄這個訊息的內容。msg_iov是乙個指向結構體struct iovec的指標,實際上,確切地說,應該是乙個結構體struct iovec的陣列。下面是該結構體的定義:

struct iovec 

;

iov_base指向資料報緩衝區,即引數buff,iov_len是buff的長度。msghdr中允許一次傳遞多個buff,以陣列的形式組織在msg_iov中,msg_iovlen就記錄陣列的長度(即有多少個buff).在我們的ping程式的示例中:

msg.msg_iov =

,iov_len =40}

}msg.msg_len =

1

(3) 第三組是msg_control和msg_controllen,它們可被用於傳送任何的控制資訊,在我們的例子中,沒有控制資訊要送。暫時略過。

(4) 第四組是msg_flags.其值即為傳入的引數flags。raw協議不支援msg_oob向標誌,即帶外資料。向核心傳送msg時使用msghdr,netlink socket使用自己的訊息頭nlmsghdr和自己的訊息位址sockaddr_nl:

關於i 和 i以及左值,右值

今天無意之間看到了帖子上有人說 i 5 不合法 i 5 合法首先對於i 的實現是 int temp temp i i i 1 return temp 而 i的實現是 i i 1 return i 所以對於我們提出來的問題已經能得到解決了 再囉嗦幾句關於i 和 i的效率問題 按上面分析來說,i的效率是...

i i等於多少?關於i 以及 i的分析

牛客網回顧錯題,有一道題很有意思,值得研究一下 下面的程式將來列印什麼?public class testincr 再看一道題,也是來自牛客網 public class q3 是不是感覺很 我剛開始看到的時候也覺得很扯淡,誰會這麼寫 我剛開始還以為編譯不通過。但是,上面兩段 確實是可以通過編譯,而且...

刪除陣列中第i個以及i後j個元素

public class deletechar yourchar deletechar.delete yourchar,2,3 system.out.println string.valueof yourchar 輸出為ab ghi 刪除陣列中從第i個元素以及後j個元素 input targetch...