看板 C_and_CPP 關於我們 聯絡資訊
: 四、 : : 如果資料被放在space buffer中且沒有做flush的動作,那資料就不會 : 被寫到文件裡。 : 例如這個C程式就會印不出字串 : : #include <stdio.h> : : int main(void) : { : printf("Hello world"); //不會顯示在終端上 : while (1); : return 0; : } : : 下面幾種行為會導致buffer flush : 1、呼叫fflush : 2、fclose : 3、exit buffered IO最終還是有一個flush時機 這邊一般來說會是 line buffered IO 所以上面如果加了\n就會印出來 : : 一、 : : 上面說到,因為我調用了C函式來操作I/O,所以C會幫我管理一個user space : 的buffer,那麼,當我不用C標準函式庫,而直接使用system call來處理 : 文件的話,是不是就沒有那個 user space buffer了? : 還有,那kernel space的buffer依然存在嗎? 的確直接呼叫syscall就不會有user space buffer這件事 kernel space有沒有就看內部實作了 小弟才學疏淺 不過一個檔案也有可能是socket pipe disk 應該還是需要一塊buffer來做處理 : : 例如這樣 : : #include <unistd.h> : #include <sys/types.h> : #include <sys/stat.h> : #include <fcntl.h> : #include <string.h> : : int main(void) : { : char str[20] = "Hello A.txt\n"; : int fdA = open("A.txt", O_WRONLY|O_CREAT, 0666); : write(fdA, str, strlen(str)); : close(fdA); : return 0; : } : : : : 二、 : : 一個程式開始前會先開啟stdin、stdout和stderr三個文件,那很多個程式 : : 同時執行時,kernel space buffer是怎麼運作的? : : 例如有三個process,p1開啟這三個文件,p2、p3亦然,他們的user space各有 : : 這三個文件的buffer,但是在kernel space中呢?也是各有三個buffer嗎? : : 讀寫的時候不會衝突嗎? 在UNIX裡有個東西叫controlling terminal (ctty) 可以想像成是登入後直接與你互動的終端 它才是真正stdin和stdout的對象 多個程式同時執行時 其實stdin stdout都指向了同一個ctty 也就是說p1, p2, p3的stdin都是同一個file 補充: fd是可以讓不同process共用的 https://swtch.com/plan9port/man/man3/sendfd.html 但只有foreground process被允許對該ctty進行操作 而background process想要讀取寫入的話 會收到SIGTTIN/SIGTTOU訊號 https://i.imgur.com/RNiMTv5.png : 三、 : : 當一個程式呼叫exit結束時,會關閉文件流並且flush user space的緩衝區, : : 請問kernel space的緩衝區會跟著被清空嗎? : : : : 四、 : : 以下程式碼 : : #include <unistd.h> : #include <stdlib.h> : : int main(void) : { : char buf[10]; : int n; : n = read(STDIN_FILENO, buf, 10); : if (n < 0) { : perror("read STDIN_FILENO"); : exit(1); : } : write(STDOUT_FILENO, buf, n); : return 0; : } : : : 編譯成a.out並執行,結果是這樣 : : $ ./a.out : hello world : hello worl$ d : -bash: d: command not found : : 我能理解當我輸入hello world時,緩衝區內會有11個字元,而這支a.out只讀了 : : 10個,所以緩衝區會剩一個d,但我不明白的是,為什麼a.out結束,返回shell後 : : shell還會讀到這個d,shell 和 a.out的緩衝區應該是分開的不是嗎? 而且a.out : : 結束後,也應該會清空緩衝區才對,我整個黑人問號,希望大家可以跟我解釋一下 : : 這個現象,謝謝。 : 呈上所述的檔案共享與controlling terminal概念 我們假設該ctty叫 /dev/pts9 原本控制/dev/pts9的process是bash 得到輸入./a.out後執行該程式 並把控制權轉交給a.out 補充: bash會呼叫tcsetgrp https://linux.die.net/man/3/tcsetpgrp 接下來我們輸入了"hello world\n"到 /dev/pts9中 (即a.out的stdin) a.out取出了10個字元 留下"d\n"在/dev/pts9中 return 0; 終止程式後 控制權交還給bash 而bash當然是繼續讀取指令 就會讀到/dev/pts9裡面的"d\n" 並嘗試執行"d" 似乎還是沒有很好的解釋出為何緩衝區沒有被清空 (或者說為何需要被清空?) 但事實上 bash跟a.out的確是使用同一個ctty (也可以說是緩衝區..) : : : : -- : : 以下是我參考的資料,問題也是閱讀這些資料時蹦出來的。 : : http://docs.huihoo.com/c/linux-c-programming/ch28s04.html : : http://blog.csdn.net/astrotycoon/article/details/44993197 這篇文章有提及蠻多關於IO的東西了 可以在理解process groups和controlling terminal後 (甚至連fork和exec那塊) 再回去看一次 補充一個這方面的連結 https://hungys.xyz/unix-prog-process-relationships/ : : : 問題有點多,如果有那裡覺得表達不清楚請跟我說下,我會再做補充。 : : 總之感激不盡,謝謝大家T_T。 : -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.46.93.105 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1495968477.A.A78.html ※ 編輯: x000032001 (114.46.93.105), 05/28/2017 19:10:05
hth9494: 感謝回答,我要消化一下_(:з」∠)_ 05/28 19:44