【Linux IO】文件描述符、重定向、缓冲区
创始人
2024-05-16 10:14:57
0

1.open函数

1.1第二个参数的解释;

O_RDONLY: 只读打开
O_WRONLY: 只写打开
O_RDWR : 读,写打开上面三个常量,必须指定一个且只能指定一个
O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
O_APPEND: 追加写
open("test.txt",O_WRONLY|O_CREAT,0644/*八进制给初始值*/);

1.2open的返回值(重点)

  • 返回值是struct file*指针数组的下标

  • 0:标准输入1:标准输出2:标准错误

#include
#include
#include
#include
#include
using namespace std;int main()
{int fd1=open("test.txt",O_WRONLY|O_CREAT,0644/*°???????*/);int fd2=open("test.txt1",O_WRONLY|O_CREAT,0644/*°???????*/);int fd3=open("test.txt2",O_WRONLY|O_CREAT,0644/*°???????*/);int fd4=open("test.txt3",O_WRONLY|O_CREAT,0644/*°???????*/);printf("%d %d %d %d\n",fd1,fd2,fd3,fd4);return 0;
}

执行结果:

原理:

2.文件描述符fd

2.1文件描述符的分配规则

上面说了,进程PCB中有一个指向files_struct的指针,这个结构体中又包含一个struct file的指针数组,打开文件就会在指针数组依次添加

那么关闭默认打开的标准输入、标准输出、标准错误文件,会发生什么结果呢?

关闭标准输入,那么新打开文件的文件描述符就是0了

#include
#include
#include
#include
#include
using namespace std;int main()
{close(0);int fd1=open("test.txt",O_WRONLY|O_CREAT,0644);if(fd1<0){cerr<<"open fail";return 1;}cout<<"fd1:"<

有上述可以得出文件描述符的分配规则:在files_struct指针数组当中,找到当前没有被使用的 最小的一个下标,作为新的文件描述符。

2.2输入输出重定向

把标准输出关闭在打开一个新文件,再打印就会发现不会打印在显示器,创建的文件中有我们打印的内容,出现了一个输出重定向;

#include
#include
#include
#include
#include
#include
using namespace std;int main()
{close(1);int fd1=open("test.txt",O_WRONLY|O_CREAT,0644);if(fd1<0){cerr<<"open fail";return 1;}cout<<"fd1:"<

输出重定向原理:

追加重定向只是在打开文件时加一个O_APPEND

#include
#include
#include
#include
#include
#include
using namespace std;int main()
{close(1);int fd1=open("test.txt",O_WRONLY|O_CREAT|O_APPEND/*这里修改了*/,0644);if(fd1<0){cerr<<"open fail";return 1;}cout<<"fd1:"<

我前面执行了几次

输入重定向

#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{close(0);int fd=open("./test.txt",O_RDONLY);if(fd<0){cerr<<"open fail";return(1);}char s[50];while(fgets(s,sizeof(s)-1,stdin))cout<

2.3dup2

需要重定向是就关闭文件是不是有些麻烦了,使用dup2函数也可以做到一样的效果;

原理:将oldfd拷贝newfd(标准输入、标准输出、标准错误)

#include
#include
using namespace std;
int main()
{int fd=open("test.txt",O_WRONLY|O_TRUNC|O_CREAT);if(fd<0){cerr<<"opne fail";return 1;}dup2(fd,1);cout<<"hello wrold"<

2.4提出一些问题

Q:如果程序替换文件描述符会改变吗?

A:不会,因为指向文件结构体的指针保存在PCB中的指向的files_struct结构体中的指针数组内,文件描述符是这个指针数组的下标,程序替换替换的是代码和数据;

Q:创建子进程,子进程文件描述符会怎么初始化和文件会新增吗?

A:子进程的PCB是使用父进程的PCB来初始化的,子进程创建PCB,文件描述符使用父进程初始化所以相同,文件当然不会新增,文件在磁盘中只有一份;

3.缓冲区

进程退出时,会将FILE内部的数据刷新到系统缓冲区,再调用系统接口,用户->OS

三种刷新策略:

1.不缓存(直接刷新)

2.行缓冲\n,endl,例:输出到显示器

3.全缓冲(把缓冲区填满就刷新到内核缓冲区),例:写入磁盘文件

#include
#include
#include
using namespace std;
int main()
{const char* s1="hello buffer\n";write(1,s1,strlen(s1));printf("hello world\n");fprintf(stdout,"hello world\n");close(1);return 0;
}

执行结果:原本打印显示器重定向写到磁盘文件,刷新策略由行刷新变为了全刷新,在函数结束前关闭了磁盘文件,保存在FILE的字符串生命周期结束,write是系统调用接口所以在写入的磁盘文件中;

3.1缓冲区属于PCB、代码、数据哪一个?

#include
#include
#include
using namespace std;
int main()
{const char* s1="hello buffer\n";write(1,s1,strlen(s1));printf("hello world\n");fprintf(stdout,"hello world\n");fork();return 0;
}

执行结果:缓冲区的数据属于数据,所以遵守写实拷贝的规则,父子进程谁先刷新谁就写实拷贝

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...