作者x000032001 (某数)
看板C_and_CPP
标题Re: [问题] 档案I/O缓冲区请益
时间Sun May 28 18:47:48 2017
: 四、
:
: 如果资料被放在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://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1495968477.A.A78.html
※ 编辑: x000032001 (114.46.93.105), 05/28/2017 19:10:05
1F:推 hth9494: 感谢回答,我要消化一下_(:з」∠)_ 05/28 19:44