1.I/O重定向node
【重定向實際上是unix系統優越性的一種體現(與管道類似);將一種操做的結果重定向到另一種操做上,這樣的思想保證了「專務專用」,將單個操做作到極致,又爲用戶本身提供了完善功能的平臺(好比重定向,好比管道)。】 - unix外殼提供了I/O重定向操做符,容許用戶將磁盤文件和標準輸入輸出鏈接起來。例如:編程
ls > foo.txt;
app
使得外殼加載和執行ls程序,將標準輸出重定向到foo.txt。函數
工做方式:spa
#include <unistd.h> int dup2(int oldfd,int newfd);
unix
拷貝描述符表項oldfd到描述符表項newfd,同時覆蓋掉newfd以前的內容。若是newfd已經打開,就先關閉newfd再進行操做。指針
調用dup2(4,1)示例:code
前提:假設描述符1(標準輸出)對應於文件A,4對應於文件B,A和B的引用計數等於1.dns
過程:兩個描述符都指向文件B,文件A已經被關閉,它以前對應的文件表和v-node也已經被刪 除;文件B的引用計數增長,以後的任何標準輸出(描述符1)的數據都被重定向到文件B。進程
2.標準I/O庫
【以前的輸入輸出函數並無特定性,而是適用於一般狀況下的I/O;標準I/O庫針對I/O的具體狀況,分類給出了特定的I/O函數;從必定角度而言,是「高級」的I/O函數。另外,與此相關的「流」的概念是和指針很類似的,也是一種「抽象」。】
總述:這個庫提供了unixI/O較高級別的替代。
類型:
流的應用: 一個流就是指向一個FILE類型的結構的指針(好比,每有一個ASNI C文件打開,都會同時打開STDIN,STDOUT,STDERR三個流)。
3.關於輸入與輸出函數的一些矛盾點
【C語言編程的時候,常常會由於輸入域輸出交叉調用致使輸入或者輸出函數不能取到想要的值】
輸入函數不能緊跟在輸出函數以後——若是輸出函數以後沒有加上fflush,fseek,fsetpos等。前者是清空與流相關的緩衝區;後二者用lseek函數重置當前的文件位置;
輸出函數不能緊跟在輸入函數以後——若是輸入函數以後沒有fseek,fsetpos,rewind等。
4.基於錯誤處理包裝函數
思想:給定的基本級系統函數foo,咱們有相同參數的、函數名大寫的包裝函數Foo;包裝函數調用基本函數並檢查錯誤。若是發現了錯誤,包裝函數就終止進程並返回一條信息;當基本函數無誤的時候,包裝函數就返回調用者。(包裝函數被封裝在源文件csapp.c中)
5.unix系統中的錯誤處理
unix風格:例如fork函數和外套函數,返回值既包括錯誤代碼,又包括有用的結果。
if((pid = wait(NULL))<0) { fprintf(stderr,"wait error:%s\n",strerror(errno));//將errno設置爲指向錯誤緣由的代碼 exit(0); }
Posix風格:例如pthread,函數只返回調用成功(0)或者失敗(非0),任何有用的信息都返回在經過調用引用進來的參數中。
DNS風格:gethostbyname和gethostbyaddr檢索NDS(域名系統)庫;它們在錯誤的時候會返回NULL,並設置全局變量h_errno。
錯誤處理包裝函數
unix風格
pid_t Wait(int *status) { pid_t pid; if(pid = wait(status)<0) unix_error("wait error"); return pid; }
Posix風格
void Pthread_detach(pthread_t tid) { int rc; if(rc=pthread_detach(tid) != 0) posix_error(rc,"Pthread_detach error"); }
DNS風格
struct hostent *Gethostbyname(const char *name) { struct hostname *p; if((p = gethostbyname(name)) == NULL) dns_error("Gethostbyname error"); return p; }