目录
重定向
文件属性操作
浅谈重定向编辑
深入重定向
dup2
缓冲区
缓冲区的理论理解
代码分析
重定向
文件属性操作
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);
ssize_t read(int fd, void *buf, size_t count);文件内容操作
read() 函数用于从文件描述符 fd 指定的文件中读取数据,将读取的数据存储到buf指向的内存缓冲区中,最多读取count字节的数据。函数返回实际读取的字节数,如果返回值为0,则表示已到达文件末尾;如果返回值为-1,则表示出现错误,此时会设置errno变量以指示具体的错误类型。
浅谈重定向
那么重定向的本质就是在内核中改变文件描述符表特定下标的内容,和上层无关。接口调用只管1,不管指向谁。
说白了就是上层不变,底层改变
当不加fflush(stdout)时数据出不来,而加fflush(stdout)数据就出来了
正常进程结束后会刷新缓冲区,但是这次不正常,在return之前要刷新的时候我close了,数据还在1号stdout那里,但是我无法通过1号写到os里,所以直接没了。把close注释掉就可以。
深入重定向
dup2
那么每次都要fflush和close很麻烦,要没有简洁的方法?就是dup2()
#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(){
int fd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);
if(fd<0){
perror("open");
return 2;
}
dup2(fd,1);
printf("fd:%d\n",fd);
fprintf(stdout,"fprintf,fd:%d\n",fd);
close(fd);
return 0;
}
最终不在显示屏输出数据,而是在log.txt中输出因为上层调用fd值1,但是fd值1指向了log.txt
缓冲区
缓冲区的理论理解
缓冲区:用户缓冲区和内核缓冲区。
几乎所有的缓冲区都有两种好处:解耦和提高效率
提高效率:主要提高的是使用者的效率和提高刷新IO的效率
我们知道调用系统调用是有成本的(没有量化的标准),所以尽量少调用效率就提高了。
比如我们使用10次printf/fprintf把数据放到c语言提供的缓冲区,10次调用printf数据都在c语言提供的缓冲区,最后只需调用一次系统调用就可以把数据写到os缓冲区,效率提高了
缓冲区是什么?其实就是一段内存空间。由c语言维护就叫语言级缓冲区,由c++维护就叫语言级缓冲区,由os维护就叫内核级缓冲区。
为什么要有缓冲区?要给上层提供良好的IO体验,(并且对大家都好,我os积攒一大批数据往硬件上刷新,我只需要硬件配合我一次。我语言层积攒一大批数据往os刷新只需os配合我一次),间接提高整体效率
缓冲区怎么办?
a.刷新策略
1. 立即刷新(相当于这个缓冲区存在价值不大,相当于没缓冲而且多了次拷贝)--fflush/fsync
2. 行刷新。显示器(显示器是给用户看的,所以行刷新主要照看用户的习惯,不快不慢)
3. 全缓冲。缓冲区写满才刷新,对应普通文件
b. 特殊情况
1. 进程退出,强制退出
2. 强制
策略代表都适用,所以上述策略用户级能用,内核级也能用,但是我们不关心内核策略我们不关心,所以只关心用户级。
代码分析
#include<unistd.h>
2 #include<stdio.h>
3 #include<stdlib.h>
4 #include<string.h>
5 int main(){
6 printf("hello printf\n");
7 fprintf(stdout,"hello fprintf\n");
8 const char*ch="hello write\n";
9 write(1,ch,strlen(ch));
10 // fork();
11 return 0;
12 }
vim /usr/include/libio.h 查看c语言提供的缓冲区,同时也可以看出条件编译
那么c++也得有,其他任何语言也得有
进程的程序替换不会影响进程关联的或者打开的文件。