epoll是linux下的乙個處理多路i/o復用的機制,基於事件通知,能夠高效的處理多個socket連線。
使用epoll,基本的函式只有三個:
(1)建立:epoll_create
(2)控制:epoll_ctl
(3)監聽:epoll_wait
2.1 建立
函式原型:
int epoll_create(int size)
函式開啟乙個epoll的檔案描述符,用於其他epoll函式呼叫。關閉的時候使用close
函式。
2.2 控制
函式原型:
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
函式用於 新增/刪除/修改 需要監聽的socket。
引數1是epoll_create
返回的控制代碼。
引數2在三個巨集定義中選擇:
epoll_ctl_add:新增需要監聽的socket和事件
epoll_ctl_mod:修改監聽的事件
epoll_ctl_del:移除監聽目標
引數3是操作的目標socket。
引數4是操作的事件引數:
typedef
union epoll_data epoll_data_t;
struct epoll_event ;
需要關注的事件:
epollin:當目標socket有資料到來時觸發。
epollout:當目標socket可寫進觸發。
epollerr:出錯時觸發。
epollhup:對方socket掛起時觸發。
epollet:使用邊緣觸發(edgetriggered)方式。預設是水平觸發(leveltriggered)。
2.3 監聽
函式原型:
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
引數2是乙個epoll_event陣列,用來儲存收到的資訊。
引數3是陣列大小。
引數4是超時時間,單位毫秒。
返回值是有事件發生的socket數量。
#include
#include
#include
#include
#include
#include
#define port 2999
#define epoll_size 2048
#define buffer_size 1024
int epoll_fd;
int listen_fd;
int create_listen_socket()
struct sockaddr_in addr;
addr.sin_family = af_inet;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inaddr_any;
int len = sizeof(addr);
if (-1 == bind(fd, (struct sockaddr*)&addr, len))
listen(fd, 10);
printf("waiting for connections...\n");
return fd;
}void my_epoll_add(int fd)
void on_accept()
}int on_read(int fd)
return -1;
}else
if(n == 0)else
}return0;}
int main(int argn, char **argv)
epoll_fd = epoll_create(epoll_size);
my_epoll_add(listen_fd);
int i, count, fd, ev, timeout = 1000;
struct epoll_event events[epoll_size];
for (;;)
ev = events[i].events;
if ((ev & epollhup) || (ev & epollerr))
if (ev & epollin)else
}else
if(ev & epollout)}}
}close(epoll_fd);
close(listen_fd);
return
0;}
邊緣觸發,就是狀態發生改變時才觸發。
水平觸發,則是狀態存在就一直會觸發。
對於epollin來說,就是水平觸發的話,只要socket裡有資料可讀,還沒讀完,則每次呼叫epoll_wait都會觸發。
而在邊緣觸發下,如果一次呼叫沒有把資料都讀完的話,則下次呼叫不會觸發,要直到下次對方有資料進來時才能繼續。而要想一次把資料讀完,則必須把socket設定成非阻塞,要不然程式就卡在read的地方了。
對於epollout來說,比較難理解。因為讀資料是被動的,可以監聽很正常,而發資料應該是個主動的過程,如何算作監聽呢?
在水平觸發下,如果設定了epollout,那麼只要socket緩衝區足夠空間,就會一直觸發可寫狀態。
而邊緣觸發下,設定了epollout,會在連線時觸發一次,然後在下次狀態由不可寫轉化為可寫時才觸發。寫緩衝區滿了的情況下會出現不可寫的狀態。
更多的時候,是程式自己呼叫epoll_ctl改變狀態來觸發寫事件,統一傳送資料,從而可以減少呼叫核心write的次數。
epoll使用簡單分析
前面說了下select和poll的優缺點及使用,現在說說linux最新的epoll機制,同樣,如有不足或錯誤之處,還請各位道友指導 epoll機制共有三個函式 epoll create int size 建立乙個epoll實體,size是提示核心內部結構的大小,並無大礙 size在linux ker...
Linux中epoll簡單使用
epoll是linux核心為處理大批量控制代碼而作了改進的poll,是linux下多路復用io介面select poll的增強版本,它能顯著減少程式在大量併發連線中只有少量活躍的情況下的系統cpu利用率。epoll預設的工作模式是level triggered,簡稱lt即水平觸發模式。是一種預設的工...
簡單的epoll模型
水平觸發模式 include include include include include include include include include int main int argc,const char ar struct sockaddr in serv addr socklen t ...