高階I O函式之sendfile函式

2021-08-25 22:27:05 字數 2146 閱讀 8310

sendfile函式在兩個檔案描述符之間傳遞資料(完全在核心中操作),從而避免了核心緩衝區和使用者緩衝區之間的資料拷貝,效率很高,被稱為零拷貝。函式定義為:

#include

ssize_t senfile(int out_fd,int in_fd,off_t* offset,size_t count);

in_fd引數是待讀出內容的檔案描述符,out_fd引數是待寫入內容的檔案描述符。offset引數指定從讀入檔案流的哪個位置開始讀,如果為空,則使用讀入檔案流預設的起始位置。count引數指定檔案描述符in_fd和out_fd之間傳輸的位元組數。首先我們來看看傳統的read/write方式進行socket的傳輸。

當需要對乙個檔案進行傳輸的時候,具體流程細節如下:

1:呼叫read函式,檔案資料copy到核心緩衝區

2:read函式返回,檔案資料從核心緩衝區copy到使用者緩衝區

在這個過程中發生了四次copy操作。

硬碟->核心->使用者->socket緩衝區(核心)->協議引擎。

而sendfile的工作原理呢??

1、系統呼叫 sendfile() 通過 dma 把硬碟資料拷貝到 kernel buffer,然後資料被 kernel 直接拷貝到另外乙個與 socket 相關的 kernel buffer。這裡沒有 使用者態和核心態 之間的切換,在核心中直接完成了從乙個 buffer 到另乙個 buffer 的拷貝。

2、dma 把資料從 kernel buffer 直接拷貝給協議棧,沒有切換,也不需要資料從使用者態和核心態,因為資料就在 kernel 裡。

測試**:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

int main(int argc,char *argv)

const

char* ip = argv[1];

int port = atoi(argv[2]);

const

char* file_name = argv[3];

int filefd = open(file_name,o_rdonly);

assert(filefd>0);

struct stat stat_buf;

fstat(filefd,&stat_buf);

struct sockaddr_in address;

bzero(&address,sizeof(address));

address.sin_family = af_inet;

inet_pton(af_inet,ip,&address.sin_addr);

address.sin_port = htons(port);

int sock = socket(pf_inet,sock_stream,0);

assert(sock>=0);

int ret = bind(sock,(struct sockaddr*)&address,sizeof(address));

assert(ret!=-1);

ret = listen(sock,5);

assert(ret!=-1);

struct sockaddr_in client;

socklen_t client_addrlength = sizeof(client);

int connfd = accept(sock,(struct sockaddr*)&client,&client_addrlength);

if(connfd<0)

else

close(sock);

return

0;}

然後進行

在另外乙個虛擬機器上telnet

高階I O函式

套接字i o操作上設定超時的方法有以下3種 1.呼叫alarm,在指定超時期滿時產生sigalrm訊號。2.在select種阻塞等待i o,一次代替直接阻塞在read或write呼叫上。3.使用較新的so rcvtimeo和so sndtimeo套接字選項。以由呼叫者指定的超時上限呼叫connect...

高階I O函式

include intpipe int fd 2 要想實現雙向的資料傳輸,應該使用兩個管道。管道內部傳輸的資料時位元組流,這和tcp位元組流的概念相同。但tcp寫入多少位元組的資料決定對方的接受視窗和擁塞視窗,而管道本身有乙個容量限制,預設是65536位元組。我們可以使用fcntl函式來修改管道容量...

高階I O之readv和writev函式

readv和writev函式用於在一次函式呼叫中讀 寫多個非連續緩衝區。有時也將這兩個函式稱為散布讀 scatter read 和聚集寫 gather write include ssize t readv int filedes,const struct iovec iov,int iovcnt ...