Re: [問題] 檔案I/O緩衝區請益

作者: x000032001 (版廢了該走了)   2017-05-28 18:47:48
: 四、
:
: 如果資料被放在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 (也可以說是緩衝區..)
:
:
:
:
作者: hth9494 (hth9494)   2017-05-28 19:44:00
感謝回答,我要消化一下_(:з」∠)_

Links booklink

Contact Us: admin [ a t ] ucptt.com