Linux下提高效能的系統調用sendfile,splice和tee熟悉Linux核心2.4版本的也許知道:在2.4版的核心中內嵌了一個叫做khttpd的靜態網頁伺服器。當時,可能是效率的因素致使她被添加了進來,至於為什麼最新的2.6版核心去掉了這個伺服器,我考慮可能是因為Linux核心“只提供機制,而不提供策略”,當然安全因素也不能排除在外。
實際上,把網頁伺服器做進核心也是完全沒有必要的,因為Linux核心提供了sendfile這樣一個系統調用:
引用:
#include <sys/sendfile.h>
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
她能把一個檔案從特定部分開始的特定塊通過一個socket發送出去,從而避免了多次調用read和write的核心上下文和使用者環境切換的開銷,並且由於其內部實現利用了mmap技術,也減少了記憶體的複製開銷。有了她,請問khttpd還有那麼必要嗎?
splice和tee是2.6.17版的Linux核心首次引入的:
引用:
#define _GNU_SOURCE
#include <fcntl.h>
long splice(int fd_in, off_t *off_in, int fd_out,
off_t *off_out, size_t len, unsigned int flags);
引用:
#define _GNU_SOURCE
#include <fcntl.h>
long tee(int fd_in, int fd_out, size_t len, unsigned int flags);
這兩個主要用來減少管道和其他描述符之間傳遞資料時的read和write系統調用的數目,詳細用法請查看man頁,其中tee的man頁中還給出了採用splice和tee重新實現的一個tee命令作為樣本,如有興趣,可查看一下。
與他們一同引入的還有vmsplice:
引用:
#define _GNU_SOURCE
#include <fcntl.h>
#include <sys/uio.h>
long vmsplice(int fd, const struct iovec *iov,
unsigned long nr_segs, unsigned int flags);
這個系統調用將使用者空間的記憶體映射到核心空間,從而避免了實際的記憶體寫操作,提高了系統效率。
不過,我並沒有覺得splice,tee和vmsplice在實際的代碼中很“有用”,倒是覺得如果能去除對管道的限制更好些。因為隧道型的代理服務程式,在串連建立後,剩下的主要任務就是在兩個socket之間互相relay資料,如果能把他們splice起來,還是能在一定程度上提高效率的。呵呵,眾口難調!
希望以上介紹對大家有益