亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

使用epoll進行高性能網絡編程

2019-11-17 05:14:07
字體:
來源:轉載
供稿:網友

  epoll和其他技術的性能比較.

翻譯:韓紅軍。hanhj@vrlab.buaa.edu.cn ; hongjun_han@163.com
原文出自:https://www.captech.com.cn
英文原文:http://www.xmailserver.org/linux-patches/nio-imPRove.Html
由于水平有限,錯誤在所難免,希望各位指正。
07-01-2001 – 初稿 - Davide Libenzi <davidel@xmailserver.org>
10-30-2002 – epoll補丁成為Linux內核一部分。請參考這個版本的,因為這個版本將會成為標準,并得到廣泛支持Davide Libenzi <davidel@xmailserver.org>
緒論:
眼下的工作是分析不同的方法,這些方法都是用來實現從內核模式高效傳遞網絡事件到用戶模式。我們考察了五種方法:作為一種相對較好的老的方法poll ,標準/dev/poll接口,標準RT信號,RT signals with one-sig-per-fd patch,和使用很非凡的通知方法的新式/dev/epoll。工作有如下四部分組成:
1) 新式 /dev/epoll 內核補丁
2) Provos-Lever修改的能夠在內核 2.4.6 工作的/dev/poll 補丁
3) HTTP server
4) 一個能夠產生“dead“連接的deadconn(tm)工具。
Httperf被采用作為度量工具,盡管不完美,但也提供了足夠的網絡負載選項。
新式 /dev/epoll 內核補?。?br />這個補丁很簡單,它在strUCt file的數據結構里面添加了通知回調鏈表項。如下代碼段:
代碼:
******* include/linux/fs.h
struct file {
...
/* 文件回調列表 */
rwlock_t f_cblock;
struct list_head f_cblist;
};



代碼:

****include/linux/fcblist.h
/* 文件回調通知事件 */
#define ION_IN 1
#define ION_OUT 2
#define ION_HUP 3
#define ION_ERR 4

#define FCB_LOCAL_SIZE 4

#define fcblist_read_lock(fp, fl) read_lock_irqsave(&(fp)->f_cblock, fl)
#define fcblist_read_unlock(fp, fl) read_unlock_irqrestore(&(fp)->f_cblock, fl)
#define fcblist_write_lock(fp, fl) write_lock_irqsave(&(fp)->f_cblock, fl)
#define fcblist_write_unlock(fp,fl) write_unlock_irqrestore(&(fp)->f_cblock, fl)

struct fcb_struct {
struct list_head lnk;
void (*cbproc)(struct file *, void *, unsigned long *, long *);
void *data;
unsigned long local[FCB_LOCAL_SIZE];
};


extern long ion_band_table[];
extern long poll_band_table[];


static inline void file_notify_init(struct file *filep)
{
rwlock_init(&filep->f_cblock);
INIT_LIST_HEAD(&filep->f_cblist);
}

void file_notify_event(struct file *filep, long *event);

int file_notify_addcb(struct file *filep,
void (*cbproc)(struct file *, void *, unsigned long *, long *), void *data);

int file_notify_delcb(struct file *filep,
void (*cbproc)(struct file *, void *, unsigned long *, long *));


void file_notify_cleanup(struct file *filep);

這些回調方法鏈就是提供一種機制,向文件系統注冊其“愛好”的上層在愛好事件發生時能夠收到底層I/O的通知。初始化和清理代碼已經加在了fs/file_table.c里,回調方法鏈處理代碼在fs/fcblist.c里面,如下所示:
代碼:
****** fs/file_table.c
struct file * get_empty_filp(void)
{
...
file_notify_init(f);
...
}

int init_private_file(struct file *filp, struct dentry *dentry, int mode)
{
...
file_notify_init(filp);
...
}

void fput(struct file * file)
{
...
file_notify_cleanup(file);
...
}
****** fs/fcblist.c
void file_notify_event(struct file *filep, long *event)
{
unsigned long flags;
struct list_head *lnk;

fcblist_read_lock(filep, flags);
list_for_each(lnk, &filep->f_cblist) {
struct fcb_struct *fcbp = list_entry(lnk, struct fcb_struct, lnk);

fcbp->cbproc(filep, fcbp->data, fcbp->local, event);
}
fcblist_read_unlock(filep, flags);
}

int file_notify_addcb(struct file *filep,
void (*cbproc)(struct file *, void *, unsigned long *, long *), void *data)
{
unsigned long flags;
struct fcb_struct *fcbp;

if (!(fcbp = (struct fcb_struct *) kmalloc(sizeof(struct fcb_struct), GFP_KERNEL)))
return -ENOMEM;
memset(fcbp, 0, sizeof(struct fcb_struct));
fcbp->cbproc = cbproc;
fcbp->data = data;
fcblist_write_lock(filep, flags);
list_add_tail(&fcbp->lnk, &filep->f_cblist);
fcblist_write_unlock(filep, flags);
return 0;
}

int file_notify_delcb(struct file *filep,
void (*cbproc)(struct file *, void *, unsigned long *, long *))
{
unsigned long flags;
struct list_head *lnk;

fcblist_write_lock(filep, flags);
list_for_each(lnk, &filep->f_cblist) {
struct fcb_struct *fcbp = list_entry(lnk, struct fcb_struct, lnk);

if (fcbp->cbproc == cbproc) {
list_del(lnk);
fcblist_write_unlock(filep, flags);
kfree(fcbp);
return 0;
}
}
fcblist_write_unlock(filep, flags);
return -ENOENT;
}

void file_notify_cleanup(struct file *filep)
{
unsigned long flags;
struct list_head *lnk;

fcblist_write_lock(filep, flags);
while ((lnk = list_first(&filep->f_cblist))) {

struct fcb_struct *fcbp = list_entry(lnk, struct fcb_struct, lnk);

list_del(lnk);
fcblist_write_unlock(filep, flags);
kfree(fcbp);
fcblist_write_lock(filep, flags);
}
fcblist_write_unlock(filep, flags);
}

這些回調函數會收到一個long *參數,其第一個元素是ION_*事件中的一種,下一個可以存儲額外的參數,這些額外參數的意義隨這第一個元素即事件種類的不同而不同。
這個接口只是一個草案,我使用它只是驗證傳輸方法是不是足夠高效。目前通知只在socket文件出現,如下:
代碼:
****** include/net/sock.h
static inline void sk_wake_async(struct sock *sk, int how, int band)
{
if (sk->socket) {
if (sk->socket->file) {
long event[] = { ion_band_table[band - POLL_IN], poll_band_table[band - POLL_IN], -1 };

file_notify_event(sk->socket->file, event);
}
if (sk->socket->fasync_list)
sock_wake_async(sk->socket, how, band);
}
}

文件fs/pipe.c和include/linux/pipe_fs_i.h也都被修改以擴展/dev/epoll的功能至管道(pipes pipe() )
兩個新的文件driver/char/eventpoll.c和include/linux/eventpoll.h實現了/dev/epoll。
新的/dev/epoll接口和以前的有很大的不同,因為他只是通過設備文件描述符映射,而基于效率考慮放棄了拷貝數據到用戶空間(copy-data- to-user-space),通過共享內存頁來避免不必要的拷貝數據/dev/epoll可以高效運作,理由有1)更少的CPU周期,因為不必拷貝數據,2)在現代的緩存的存儲體系架構下,有更少的內存占用(memory footprint)。
/dev/epoll實現利用新的文件回調通知機制來注冊回調方法,這些回調方法將事件存儲事件緩沖區里,初始化順序如下:
代碼:
if ((kdpfd = open("/dev/epoll", O_RDWR)) == -1) {

}
if (ioctl(kdpfd, EP_ALLOC, maxfds))
{

}
if ((map = (char *) mmap(NULL, EP_MAP_SIZE(maxfds), PROT_READ,
MAP_PRIVATE, kdpfd, 0)) == (char *) -1)
{

}

maxfds 能夠存儲在輪詢設備里面的最多的文件描述符數目,文件通過下面代碼注冊進愛好集里面:
代碼:
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLIN POLLOUT POLLERR POLLHUP;
pfd.revents = 0;
if (write(kdpfd, &pfd, sizeof(pfd)) != sizeof(pfd)) {
...
}

下面代碼刪除指定的文件描述符:
代碼:
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLREMOVE;
pfd.revents = 0;
if (write(kdpfd, &pfd, sizeof(pfd)) != sizeof(pfd)) {
...
}

核心分派(dispatch)代碼類似下面:
代碼:
struct pollfd *pfds;
struct evpoll evp;

for (;;) {
evp.ep_timeout = STD_SCHED_TIMEOUT;
evp.ep_resoff = 0;

nfds = ioctl(kdpfd, EP_POLL, &evp);
pfds = (struct pollfd *) (map + evp.ep_resoff);

for (ii = 0; ii < nfds; ii++, pfds++) {
...
}
}


驅動程序分配兩個頁面集來作為雙緩沖機制,存儲文件事件。可以從ep_resoff字段得知結果集在map里面的哪一塊。在使用其中一個頁面集的同時,內核可以使用另外一個存儲進來的事件們。沒有拷貝到用戶空間的麻煩,來自同一個文件的事件將被放在一個槽(slot)里面,EP_POLL函數決不會線性查找愛好集來執行file->f_ops->poll()。為了使用/dev/epoll接口,你必須使用mknod創建該文件,并且major =10 and minor=124。命令如下:
# mknod /dev/epoll c 10 124
下載補丁在下面的鏈接
epoll-lt-2.4.24-0.20.diff

Provos-Lever的/dev/poll補丁:
這個值得說的不多,修改virt_to_page()這個漏洞就可以使補丁正常工作,我修改了另外一個bug,程序為了調節哈希表大小,而試圖使用 kmalloc()分配大塊內存卻不能滿足,現在使用vmalloc()來為哈希表分配內存。我修改了在CITI網站上發現的2.4.3的補丁,這個補丁應該是Provos-Lever用來使(2.2.x)升級到2.4.x的那個。你可以在如下地址下載到:
http://www.xmailserver.org/linux-patches/olddp_last.diff.gz

實時信號一個文件描述符一個信號(one-sig-per-fd)補丁:
Vitaly Luban貢獻的這個補丁實現了實時信號量,當實時信號量隊列滿了的時候,盡量避免SIGIO傳輸信息,你可以下載這個補丁如下網址:
http://www.luban.org/GPL/gpl.html

HTTP服務器:
http服務器很簡單,它使用的是事件輪詢和同步程序庫(coroutines),服務器內部的coroutine庫的實現來自如下網址:
http://www.goron.de/~froese/coro/
它很小,簡單且高效。服務器使用的默認堆棧大小為8192,當試圖有許多連接時,將造成內存浪費和虛存顛簸(vm trashing),其實4096的堆棧大小就足夠了。另外一個問題是coro庫使用mmap()方法來為堆棧分配空間,這樣當accept() /close()比率較高時會損失性能,我改了這個庫(只有一個文件coro.c)讓其使用malloc()/free()而不是mmap() /munmap().每次的Http應答都一樣,應答的報文大小可以通過命令行參數設置,另外還有兩個命令行參數可以設置監聽端口和fd集的大小。你可以在如下地址下載到服務器:
ephttpd-0.2.tar.gz
老版本:
http://www.xmailserver.org/linux-patches/dphttpd_last.tar.gz

死連接工具:
假如說上面的服務器簡單,這個就更簡單了,它的目的就是給服務器制造死連接來模擬真實的負栽,這些連接都是一批的低速連接。你可以下載到:
http://www.xmailserver.org/linux-patches/deadconn_last.c

測試:
測試環境:PIII 600MHz, 128 Mb RAM, eepro100網卡連接到100Mbps快速以太網交換機上。RH 6.2,使用的內核是2.4.6, coroutine 庫的版本是1.1.0-pre2
我使用雙PIII 1GHz, 256 Mb RAM 和雙eepro100作為httperf機器,雙PIII 900 MHz, 256 Mb RAM 和雙 eepro100作為deadconn(tm)機器,因為httperf當使用較高的num-conns時占用fds空間(改為8000了)很快消失,我采用了下面的命令行:
--think-timeout 5 --timeout 5 --num-calls 2500 --num-conns 100 --hog --rate 100
這個將分配100個連接,使服務器負栽不同的死連接。我改變的另一個參數是應答報文大小有128,512和1024。另外一個更加忠實于互聯網會話就是使用一些突發連接發出HTTP請求,然后關閉,測試使用httperf,并有如下命令:
--think-timeout 5 --timeout 5 --num-calls 2 --num-conns 27000 --hog --rate 5000
每個數字都是求得三次的平均值,如下地址下載httperf:
http://www.hpl.hp.com/personal/David_Mosberger/httperf.html



測試顯示/dev/epoll約比RT signals one-sig實現快10-12%,/dev/epoll和RT signals都保持平坦在不同的死連接負栽下。
RT-one-sig實現比簡單 實時信號實現要快一點, 但是本測試只有很少的 SIGIO.




512和1024 Content-Length 的應答報文測試表明 /dev/epoll, RT signals和RT one-sig 表現基本一致,圖中重疊在一塊了, 這是因為在本測試中以太網達到了飽和態( 100Mbps )。


這個測試表明/dev/epoll, RT signals 和RT one-sig實現在不同死連接情況下的每秒的Http應答報文一直平坦,并且/dev/epoll大約15% 快于RT one-sig ,而RT one-sig 大約10-15% 快于簡單 RT signals.


系統調用接口( aka sys_epoll ):
事件查詢設備對于系統調用接口的需要促成了sys_epoll系統調用的實現,這個簡單接口為開發人員實現了同樣的可擴展性。新的系統調用引入了三個新的映射到用戶空間的調用:
int epoll_create(int maxfds);
int epoll_ctl(int epfd, int op, int fd, unsigned int events);
int epoll_wait(int epfd, struct pollfd *events, int maxevents, int timeout);
這些函數在他們的手冊頁面里面描述:
epoll : PSTXTMAN
epoll_create : PS TXTMAN
epoll_ctl : PSTXT MAN
epoll_wait : PSTXT MAN
實現這些系統調用的補丁在這兒. 一個新的訪問epoll ( 2.5.45 )的庫在這個可得到: epoll-lib-0.11.tar.gz

一個簡單基于管道的epoll性能測試:
pipetest

用戶空間支持epoll的庫 :
libevent
ivykis
在測試epoll過程中,做的一個 thttpd 的補丁:
thttpd.epoll.diff
結論:
這些數據顯示/dev/epoll ( and sys_epoll )提高了服務器的效率(從應答報文速率和CPU利用率角度看)。/dev/epoll的應答速率完全獨立于死連接的數目,而標準poll()和舊的 /dev/poll似乎不可避免的受到影響。和標準poll()以及舊的/dev/poll相比/dev/epoll的方差也明顯小的多,這不盡使我覺得 (1) 將有跟多的處理能力(2)在高負栽下有可以預見的應答速率。RT signals和RT one-sig 是現在死連接變化時也基本保持不變,并且one-sig大約比簡單RT signals快10-12% 。RT singnals實現 (即使 one-sig 較少)似乎不能適用于大量突發請求模擬真實因特網的情況,在這種情況下有大量連接處于active狀態。這是因為RT signals隊列的限制,即使打了one-sig的補丁, 也很輕易填滿隊列。
鏈接:
[1] The epoll scalability page at lse.
[2] David Weekly - /dev/epoll Page

References:
[1] W. Richard Stevens - "UNIX Network Programming, Volume I: Networking APIs: Sockets and XTI, 2nd edition"
Prentice Hall, 1998.
[2] W. Richard Stevens - "TCP/IP Illustrated, Volume 1: The Protocols"
Addison Wesley professional computing series, 1994.
[3] G. Banga and J. C. Mogul - "Scalable Kernel Performance for Internet Servers Under Realistic Load"
Proceedings of the USENIX Annual Technical Conference, June 1998.
[4] G. Banga. P. Druschel. J. C. Mogul - "Better Operating System Features for Faster Network Servers"
SIGMETRICS Workshop on Internet Server Performance, June 1998.
[5] G. Banga and P. Druschel - "Measuring the Capacity of a Web Server"
Proceedings of the USENIX Symposium on Internet Technologies and Systems, December 1997.
[6] Niels Provos and Charles Lever - "Scalable Network I/O in Linux"
http://www.citi.umich.edu/techreports/reports/citi-tr-00-4.pdf
[7] Dan Kegel - "The C10K problem"
http://www.kegel.com/c10k.html
[8] Richard Gooch - "IO Event Handling Under Linux"
http://www.atnf.csiro.au/~rgooch/linux/docs/io-events.html
[9] Abhishek Chandra and David Mosberger - "Scalability of Linux Event-Dispatch Mechanisms"
http://www.hpl.hp.com/techreports/2000/HPL-2000-174.html
[10] Niels Provos and Charles Lever - "Analyzing the Overload Behaviour of a Simple Web Server"
http://www.citi.umich.edu/techreports/reports/citi-tr-00-7.ps.gz
[11] D. Mosberger and T. Jin - "httperf -- A Tool for Measuring Web Server Performance"
SIGMETRICS Workshop on Internet Server Performance, June 1998.

上一篇:生成靜態連接庫

下一篇:Pcap程序設計

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日韩国产精品一区二区不卡中文| 欧美黄色小视频| 亚洲电影免费观看高清完整版| 久久久亚洲精品视频| 欧美黑人巨大xxx极品| 亚洲国产另类 国产精品国产免费| 日韩中文字幕av| 欧美国产日韩xxxxx| 久久777国产线看观看精品| 韩国19禁主播vip福利视频| 91美女片黄在线观看游戏| 欧美激情2020午夜免费观看| 久久久av网站| 欧美激情a∨在线视频播放| 久久福利视频导航| 黑人精品xxx一区| 国产精品va在线播放我和闺蜜| 欧美日韩国产精品一区二区三区四区| 欧美日本国产在线| 高清欧美性猛交xxxx黑人猛交| 亚洲精品福利在线| 色老头一区二区三区| 亚洲第一精品自拍| 午夜精品久久久99热福利| 最近2019中文字幕在线高清| 亚洲欧美另类中文字幕| 久久久中文字幕| 日本一区二三区好的精华液| 69av在线视频| 狠狠色噜噜狠狠狠狠97| 91精品国产高清自在线| 国产成人精品午夜| 成人乱色短篇合集| 91av国产在线| 亚洲男人天堂九九视频| 中文字幕在线看视频国产欧美| 亚洲精品网站在线播放gif| 久久久久久有精品国产| 韩国视频理论视频久久| 91精品久久久久| 国产精品久久久久aaaa九色| 欧美老妇交乱视频| 亚洲成人aaa| 一本色道久久综合狠狠躁篇怎么玩| 亚洲天堂2020| 日韩有码视频在线| 成人高h视频在线| 久久成人亚洲精品| 一本一本久久a久久精品综合小说| 欧美大尺度电影在线观看| 日韩欧美在线中文字幕| 久久久久久国产精品三级玉女聊斋| 欧美极品欧美精品欧美视频| 久久99国产综合精品女同| 91性高湖久久久久久久久_久久99| 国产精品色午夜在线观看| 欧美成人中文字幕在线| 久久久久国色av免费观看性色| 91干在线观看| 91av在线视频观看| 一本色道久久88综合日韩精品| 最近2019中文免费高清视频观看www99| 欧美电影免费观看高清完整| 久久久久久久久久久免费| 成人免费福利在线| 91精品视频网站| 成人春色激情网| 欧美日韩午夜激情| 欧美黑人xxxⅹ高潮交| 欧美专区国产专区| 成人黄色大片在线免费观看| 91成人免费观看网站| 中文字幕在线日韩| 38少妇精品导航| 成人免费午夜电影| 日韩av影视在线| 亚洲电影天堂av| 国产视频自拍一区| 久久久久久久香蕉网| 国产精品久久综合av爱欲tv| 亚洲女性裸体视频| 日本韩国在线不卡| 亚洲欧美日韩中文在线| 欧美尤物巨大精品爽| 久久久国产影院| 国产精品伦子伦免费视频| 精品成人国产在线观看男人呻吟| 日韩精品中文字幕在线观看| 黄色成人av在线| 综合136福利视频在线| 亚洲精品综合精品自拍| 91在线视频免费| 亚洲第一精品久久忘忧草社区| 国产精品入口日韩视频大尺度| 久久久噜久噜久久综合| 精品国产一区二区三区四区在线观看| 亚洲欧美日韩精品久久亚洲区| 日本精品性网站在线观看| 国产精品v日韩精品| 日韩av影视综合网| 欧美激情视频一区二区三区不卡| 国产精品丝袜久久久久久不卡| 国产综合香蕉五月婷在线| 欧美野外猛男的大粗鳮| 中文字幕精品在线| 夜夜狂射影院欧美极品| 亚洲精选在线观看| 日韩中文字幕国产精品| 国产精品18久久久久久麻辣| 日韩精品在线观| 久久天天躁狠狠躁夜夜爽蜜月| 亚洲综合中文字幕在线| 色综合亚洲精品激情狠狠| 少妇精69xxtheporn| 久久99精品国产99久久6尤物| 日韩专区在线播放| 91成人在线播放| 亚洲图片制服诱惑| 在线看片第一页欧美| 欧美激情奇米色| 国产精品丝袜白浆摸在线| 在线播放国产精品| 欧美日韩国产丝袜美女| 96国产粉嫩美女| 68精品久久久久久欧美| 91极品视频在线| 青青草国产精品一区二区| 亚洲第一视频网站| 北条麻妃久久精品| 日韩亚洲欧美中文高清在线| 最近中文字幕日韩精品| 青青草精品毛片| 3344国产精品免费看| 91在线|亚洲| 91精品在线影院| 日韩在线免费视频观看| 欧美黑人xxxⅹ高潮交| 清纯唯美亚洲激情| 欧美中文字幕在线视频| 久久久国产一区二区| 午夜精品蜜臀一区二区三区免费| 国产成+人+综合+亚洲欧洲| 欧美大片在线免费观看| 国产一区二区三区久久精品| 在线观看日韩www视频免费| 欧美精品videos| 欧美成人免费va影院高清| 亚洲少妇中文在线| 色妞在线综合亚洲欧美| 亚洲国产精品成人va在线观看| 亚洲香蕉伊综合在人在线视看| 国产精品九九九| 亚洲女人天堂成人av在线| 国产亚洲欧洲高清一区| 色哟哟入口国产精品| 欧美一级电影免费在线观看| 欧美黄网免费在线观看| 国产精品久久久久久久久| 久久九九亚洲综合| 欧美日韩国产中文精品字幕自在自线| 欧美精品国产精品日韩精品| 激情av一区二区| 日韩亚洲欧美成人| 国产剧情久久久久久|