(1) I/O 模型的選擇,
epoll就一定好嗎? 那是肯定的。
epoll最有用的就是ET模式,適合於那種有大量串連,但是有資料的串連比較少的情況,
如果你有10000個串連,但是很不幸,這10000個串連全部都有資料,你還是得遍曆一把進行處理,( 這裡對ET模式下怎麼處理資料就不討論了)。
這個和select, poll有什麼區別。
epoll還有比select, poll先進得地方, 就在於將fd得列表維護在核心中, 而select, poll是調用一次,傳遞一次, 這點epoll領先是沒得說得。
最主要還是epoll系統調用的實現方式採用事件方式,比poll, select的輪詢方式強的多
(2) 使用非堵塞
做為網路伺服器, 堵塞I/O一般情況下不予考慮
(3) 減少I/O操作和無謂的系統調用
比如利用writev一次性寫入多個資料, 減少write調用的次數.
或者使用零拷貝的sendfile,tee等
(4) tcp是雙工的
這點不要忽略掉, 資料轉寄程式就在於資料的轉寄速度, 這裡我採用讀和寫分開線程的處理方式
(5) 進程還是線程
這個無關緊要,一個粒度和資料訪問, 穩定性的問題。減少之間的相互影響,盡量沒有關聯, 比如減少對相關互斥資料的訪問等等。
(6) 盡量在設計上做到不需要鎖
比如使用環形緩衝, 環形訊息佇列等
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/pmunix/archive/2008/07/18/2672975.aspx
| writev() function |
/* prototype: ssize_t writev(int fd, const struct iovec *iov, int cnt); */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/uio.h> int main(void) { char buf0[] = "xuzhengyang", buf1[] = "yinshulei/n"; struct iovec iov[2]; iov[0].iov_base = buf0; iov[0].iov_len = strlen(iov[0].iov_base); iov[1].iov_base = buf1; iov[1].iov_len = strlen(iov[1].iov_base); if (writev(STDOUT_FILENO, iov, 2) == -1) { perror("writev"); exit(1); } exit(0); } |
|
|
|
Sendfile函數說明
#include <sys/sendfile.h>
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
sendfile()是作用於資料拷貝在兩個檔案描述符之間的操作函數.這個拷貝操作是核心中操作的,所以稱為"零拷貝".sendfile函數比起read和write函數高效得多,因為read和write是要把資料拷貝到使用者應用程式層操作.
參數說明:
out_fd 是已經開啟了,用於寫操作(write)的檔案描述符;
in_fd 是已經開啟了,用於讀操作(read)的檔案描述符;
offset 位移量;表示sendfile函數從in_fd中的哪一位移量開始讀取資料.如果是零表示從檔案的開始讀,否則從相應的便宜量讀取.如果是迴圈讀取的時候,下一次offset值應為sendfile函數傳回值加上本次的offset的值.
count是在兩個描述符之間拷貝的位元組數(bytes)
傳回值:
如果成功的拷貝,返回寫操作到out_fd的位元組數,錯誤返回-1,並相應的設定error資訊.
EAGAIN 無阻塞I/O設定O_NONBLOCK時,寫操作(write)阻塞了.
EBADF 輸出或者輸入的檔案描述符沒有開啟.
EFAULT 錯誤的地址.
EINVAL 描述符不可用或者鎖定了,或者用mmap()函數操作的in_fd不可用.
EIO 當讀取(read)in_fd時發生未知錯誤.
ENOMEM 讀(read)in_fd時記憶體不足.
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/Crazyguang/archive/2008/05/09/2423708.aspx