tee函數使用
功能描述:tee函數在兩個管道文件描述符之間復制數據,也是零拷貝操作.它不消耗數據,因此源文件描述符仍然可以用於後續的操作.
函數原型:
#include <fcntl.h> ssize_t tee(int fd_in,int fd_out,size_t len,unsigned int flags);
函數參數:fd_in和fd_out必須都是管道文件描述符。
返回值:成功時返回在兩個文件描述符之間復制的數據字節數,返回0表示沒有復制任何數據.失敗時返回-1並設置errno.
下面是利用tee函數和splice函數,實現同時輸出數據到終端與文件的程序)的基本功能.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <assert.h> #include <errno.h> #include <fcntl.h> int main(int argc,const char* argv[]){ if(argc<=2){ printf("usage:%s <file>\n",argv[0]); exit(-1); } int filefd=open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0666); assert(filefd>=0); int pipefd_stdout[2]; int ret=pipe(pipefd_stdout); assert(ret!=-1); int pipefd_file[2]; ret=pipe(pipefd_file); assert(ret!=-1); /*將標准輸入內容輸入管道文件pipefd_stdout*/ ret=splice(STDIN_FILENO,NULL,pipefd_stdout[1],NULL,32768,SPLICE_F_MORE |SPLICE_F_MOVE); assert(ret!=-1); /*將管道pipefd_stdout[0]輸出復制到管道pipefd_file的輸入端*/ ret=tee(pipefd_stdout[0],pipefd_file[1],32768,SPLICE_F_NONBLOCK); assert(ret!=-1); /*將管道pipefd_file的輸出定向到文件描述符filefd上*/ ret=splice(pipefd_file[0],NULL,filefd,NULL,32768,SPLICE_F_MORE| SPLICE_F_MORE); assert(ret!=-1); /*將管道pipefd_stdout的輸出定向到標准輸出,其內容與文件中完全一致*/ ret=splice(pipefd_stdout[0],NULL,STDOUT_FILENO,NULL,32768,SPLICE_F_MORE| SPLICE_F_MOVE); assert(ret!=-1); close(filefd); close(pipefd_file[0]); close(pipefd_file[1]); close(pipefd_stdout[0]); close(pipefd_stdout[1]); return 0; }
fcntl函數的使用
功能描述:常用於控制文件描述符的屬性和行為
函數原型:
#include <fcntl.h> int fcntl(int fd,int cmd,...);
fd是被操作的文件描述符,cmd參數指定執行何種類型的操作.根據操作類型的不同,該函數可能還需要第三個可選參數.
fcntl支持的常用操作及其參數
操作分類 操作 含義 第三個參數的類型 成功時的返回值 復制文件描述符 F_DUPFD 創建一個新的文件描述符,其值大於或等於arg long 新創建的文件描述符的值 F_DUPFD_CLOEXEC 與F_DUPFD相似,不過在創建文件描述符的同時,設置其close_on_exec標志 long 新創建的文件描述符的值 獲取和設置文件描述符的標志 F_GETFD 獲取fd的標志 無 fd的標志 F_SETFD 設置fd的標志 long 0 獲取和設置文件描述符的狀態標志 F_GETFL 獲取fd的狀態標志,這些標志包括可由open系統調用設置的標志(O_CREAT、O_APPEND等)和訪問模式(O_RDONLY、O_WRONLY和O_RDWR) void fd的狀態標志 F_SETFL 設置fd的狀態標志,但部分標志是不能修改的(比如訪問模式標志) long 0 管理信號 F_GETOWN 獲得SIGIO和SIGURG信號的宿主進程的PID或進程組的ID 無 信號的宿主進程或者進程組ID F_SETOWN 設定SIGIO和SIGURG信號的宿主進程的PID和進程組的ID long 0 F_GETSIG 獲取當應用程序被通知fd可讀或可寫時,是哪個信號通知該事件的 無 信號值 F_SETSIG 設置當fd可讀或可寫時,系統應該觸發哪個信號來通知應用程序 long 0 操作管道容量 F_SETPIPE 設置由fd指定的管道的容量 long 0 F_GETPIPE 獲取由fd指定的管道的容量 無 管道容量
估計fcntl返回失敗-1,O_WRONLY|O_TRUNC不能更改
fcntl的文件狀態有7個:O_RDONLY,O_WRONLY,O_RDWR,O_NONBLOCK,O_APPEND,O_SYNC(異步I/O),O_ASYNC(等待寫完成),
可以更改的標志是O_APPEND,O_NONBLOCK,O_SYNC,O_ASYNC。(沒有O_EXEC等其他的)
O_NONBLOCK:非阻塞I/O,如果read(2)調用沒有可讀的數據,或者如果write(2)操作將阻塞,則read或write調用將返回-1和EAGAIN錯誤。
O_APPEND:強制每次寫(write)操作都將添加在文件大的末尾,相當於open(2)的O_APPEND標志。
O_DIRECT:最小化或去掉reading和writing的緩存影響。系統將企圖避免緩存你的讀或寫的數據,如果不能避免緩存,那麼它將最小化已經被緩存了的數據造成的影響。如果這個標志用的不夠好,將大大降低性能。
O_ASYNC:當I/O可用的時候,允許SIGIO信號發送到進程組,例如:當有數據可讀的時候。
fcntl使用結構體的形式如下:
int fcntl(int fd, int cmd, struct flock *lock);如果你是這樣聲明並使用的,應該使用指針的->操作符:
struct flcok *lock;var=fcntl(atoi(argv[1]), F_GETFL, lock);如果你是如下聲明並使用的,應該使用結構體的.操作符:
struct flcok lock;var=fcntl(atoi(argv[1]), F_GETFL, &lock);//用取地址符&傳遞指針參數這個聲明是非指針結構體,通過地址傳值給指針結構體參數,在外部操作上不能用->指針操作符。