【學習時間:8小時】 【學習內容:教材第十章 之 I/O總結;實驗樓私有課程《深刻理解計算機系統》 之 系統級I/O】html
【重定向實際上是unix系統優越性的一種體現(與管道類似);將一種操做的結果重定向到另一種操做上,這樣的思想保證了「專務專用」,將單個操做作到極致,又爲用戶本身提供了完善功能的平臺(好比重定向,好比管道)。】 - unix外殼提供了I/O重定向操做符,容許用戶將磁盤文件和標準輸入輸出鏈接起來。例如:node
ls > foo.txt;
使得外殼加載和執行ls程序,將標準輸出重定向到foo.txt。linux
工做方式:web
#include <unistd.h> int dup2(int oldfd,int newfd);
拷貝描述符表項oldfd到描述符表項newfd,同時覆蓋掉newfd以前的內容。若是newfd已經打開,就先關閉newfd再進行操做。編程
前提:假設描述符1(標準輸出)對應於文件A,4對應於文件B,A和B的引用計數等於1.ubuntu
過程:兩個描述符都指向文件B,文件A已經被關閉,它以前對應的文件表和v-node也已經被刪 除;文件B的引用計數增長,以後的任何標準輸出(描述符1)的數據都被重定向到文件B。安全
【以前的輸入輸出函數並無特定性,而是適用於一般狀況下的I/O;標準I/O庫針對I/O的具體狀況,分類給出了特定的I/O函數;從必定角度而言,是「高級」的I/O函數。另外,與此相關的「流」的概念是和指針很類似的,也是一種「抽象」。】併發
【C語言編程的時候,常常會由於輸入域輸出交叉調用致使輸入或者輸出函數不能取到想要的值】app
unix風格:例如fork函數和外套函數,返回值既包括錯誤代碼,又包括有用的結果。函數
if((pid = wait(NULL))<0) { fprintf(stderr,"wait error:%s\n",strerror(errno));//將errno設置爲指向錯誤緣由的代碼 exit(0); }
錯誤處理包裝函數
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; }
【參考上面的函數,標準輸入的描述符爲0,則使用:
int dup2(5,0);
進行重定向。】
#include "csapp.h" int main() { int fd1,fd2; char c; fd1 = Open("foobar.txt",O_RDONLY,0); fd2 = Open("foobar.txt",0_RDONLY,0); Read(fd2,&c,1); Dup(fd2,fd1); Read(fd1,&c,1); printf("c= %c\n",c); exit(0); }
【fd1被重定向到了fd2,因此輸出的是第二個字母(以前的第一個字母‘f’已經被讀過了):‘o’】
【當父進程打開子進程以後,父子進程併發執行,並且,兩者結束的前後順序是不可控制的;最後,當子進程被打開以後,父子進程以後的部分是同樣的;並且,最後的結果前後沒法區分】
1.開始運行練習題10.1的代碼時,編譯出錯,顯示是由於沒法找到「csapp.h」文件
#include "csapp.h" int main() { int fd1,fd2; fd1=Open("foo.txt",O_RDONLY,0); Close(fd1); fd2=Open("baz.txt",O_RDONLY,0); printf("fd2=%d\n",fd2); exit(0); }
經過網上搜索,發現一篇博客給出瞭解答:
這一週老師給佈置了一個有關IO的Open函數的實驗,叫咱們本身到linux上去運行一下,結果在csapp.h這個頭文件上糾結了很久,在這裏特別總結一下,留個記念. 是csapp.h其實就是一堆頭文件的打包,在http://csapp.cs.cmu.edu/public/code.html 這裏能夠下載。這是《深刻理解計算機系統》配套網站,但有個疑問是csapp.h這個 是做者寫的?仍是出自unix的源代碼了?但毫無疑問他給咱們寫一些程序的編寫帶來了方便,有了它咱們就不必在寫那麼多頭文件了,一個就搞定。至於出處的話,就不糾結了,會用就行。
在linux下要怎麼使用頭文件了,linux應該沒有自帶csapp.h,因此要本身導入,我用的是fedora的,要放到 /usr/include的文件夾裏面。打開後這裏面有好多頭文件... (ubuntu下是/usr/lib,其餘版本的linux應該也是在usr的目錄下吧)。另外還有一點,要在頭文件的#end if前面加上一句#include <csapp.c>,由於那個頭文件要把csapp.c文件包含進去 這樣的話就能夠用了。
還有就是由於csapp.c中有關於線程的頭文件,在用gcc的時候最後要加上-lpthread 如 # gcc -o Ex Ex.c -lpthread
【也就是沒法經過「複製」——「粘貼」完成csapp.h的添加】
【通過小組提問,發現能夠經過命令行終端的mv命令進行操做】
【結果失敗】
本次學習是對以前學習的精細化過程;由於知識性的新內容很少,因此我就把大部分精力放在了實踐上。對於課本上的代碼,儘可能去打出來運行;對於以前想嘗試但一直沒有嘗試的linux命令或者功能學習,盡力去練習。看似抓住的很少,然而不斷的嘗試和失敗再到成功,也是頗有教育意義的。