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