基础IO(一)

🌟🌟hello,各位读者大大们你们好呀🌟🌟
🚀🚀系列专栏:【Linux的学习】
📝📝本篇内容:文件基础概念;C语言接口回顾;系统接口;文件系统调用;三个标准;输出缓冲区
⬆⬆⬆⬆上一篇:C++中的继承
💖💖作者简介:轩情吖,请多多指教(> •̀֊•́ ) ̖́-

1.文件基础概念

①文件=属性+内容->针对文件的操作,对内容的操作,对属性的操作
②当文件没有被操作时,一般在磁盘
③当我们对文件进行操作时,文件需要在内存(冯诺依曼体系)
④先描述,构建在内存中的文件结构体struct file(文件一些属性可以从磁盘中来)
⑤每一个被打开的文件,都要在OS内对应文件对象的struct结构体,可以将所有的struct file结构体用某种数据结构连接起来,在OS内部,对被打开的文件进行管理,转换成了对链表的增删查改,总结来说就是文件被打开,OS要为被打开的文件,创建对应的内核数据结构
struct file
{
//各种属性、连接关系
}
⑥文件分为磁盘文件和被打开的文件(内存文件)
⑦文件是OS打开的,是用户(进程)让OS打开的
⑧都是进程和被打开文件的关系:struct task_struct和struct file

2.C语言接口回顾

①w:默认写方式打开文件,如果文件不存在,就创建它,默认如果只是打开,文件内容会被自动清空,每次写入都会从最开始进行写入
在这里插入图片描述
在这里插入图片描述

②a:不会清空文件,而是每一次写入都是从文件结尾写入的(追加)
在这里插入图片描述
在这里插入图片描述

3.系统接口

①int open(const char* pathname,int flags,mode_t mode);
在这里插入图片描述
在这里插入图片描述
其中mode是权限的设置,flags是位图的使用,int是32个比特位,我们可以用一个比特位表示一个标志位,可以看下面的代码来理解一下位图的使用

 1 #include <stdio.h>
  2 #define ONE 0x1//00000000000000000000000000000001
  3 #define TWO 0x2//00000000000000000000000000000010
  4 #define FOUR 0x4//00000000000000000000000000000100
  5 #define EIGHT 0x8//00000000000000000000000000001000
  6 void Print(int x)
  7 {
  8   //充当不同行为                                                                                                                                                    
  9   if(x&ONE)          
 10   {                  
 11     printf("NOE\n"); 
 12   }                  
 13                      
 14   if(x&TWO)          
 15   {                  
 16     printf("TWO\n"); 
 17   }                  
 18   if(x&FOUR)         
 19   {                  
 20     printf("FOUR\n");
 21   }                  
 22   if(x&EIGHT)        
 23   {                   
 24     printf("EIGHT\n");
 25   }                  
 26 }                    
 27 int main()           
 28 {                    
 29 Print(ONE|TWO|EIGHT);
 30                      
 31            
 32   return 0;
 33 }

在这里插入图片描述

O_WRONLY:只写,默认不会对原始文件内容做清空
O_CREAT:没有文件则创建文件
O_TRUNC:清空文件
O_APPEND:追加
O_RDONLY:只读
②ssize_t write(int fd,const void* buf,size_t count)
在这里插入图片描述
③ssize_t read(int fd, void *buf, size_t count);
在这里插入图片描述
代码测试:

//write的使用
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h> 
using namespace std;
int main()
{
  umask(0);//修改掩码为0000
  int fd=open("./config.txt",O_CREAT|O_WRONLY,0664);//mode表示权限   
  if(fd==-1)
  {
    return -1;
  }
  char buff[1024]="1234\n56789";//'\0'是C语言规定的,不是文件的规定   
  write(fd,buff,5);
  close(fd);
  return 0;
}

在这里插入图片描述

//read的使用
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h> 
using namespace std;
int main()
{
    int fd=open("./config.txt",O_RDONLY);
    if(fd==-1)
    {
      return -1;
    }
    char buff[1024];
    int n=read(fd,buff,1023);//'\0'是C语言规定的,不是文件的规定
    if(n==-1)//read函数的返回值表示的是读取了多少字节         
    {
      return -1;
    }
    close(fd);
    buff[n]='\0';
    cout<<buff;
    

  return 0;
}

在这里插入图片描述
使用系统接口进行IO的时候一定要注意‘\0’的问题,这里我们无法做到按行读取,我们是整体读取的,其实本质上库函数底层也会调用系统调用

4.文件系统调用

任何一个进程,在启动的时候,默认会打开当前进程的三个文件:
在这里插入图片描述
现在来解释一下open的返回值:文件描述符,本质上其实是数组下标
在这里插入图片描述
我们使用OS的本质:都是通过进程的方式进行OS的访问的
在对于文件访问当中也会包含对于显示器,键盘等硬件的访问,而硬件访问就会比较复杂,因此在此类文件的struct file中会有对应的函数指针
在这里插入图片描述
FILE是一个结构体,C语言提供的
操作系统层面,我们必须要访问fd,我们才能找到文件
任何语言层访问外设或者文件,必须经历OS
在FILE里必定封装了fd

5.三个标准

进程中,文件描述符的分配规则:在文件描述符表中,最小的,没有被使用的数组元素,分配给新文件
其实本质上重定向的原理就是在上层无法感知的情况下,在OS内部,更改进程对应的文件描述符表中特定下标的指向!!!
其中stdout,cout本质他们内部的fd是1号文件描述符,他们都是向1号文件描述符对应的文件打印
stderr,cerr本质他们内部的fd是2号文件描述符,他们都是向2号文件描述符对应的文件打印
因此,输出重定向,只改的是1号对应的指向
代码验证:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
新的使用方法:
在这里插入图片描述
在这里插入图片描述
其中那行命令意思是把1号文件描述符所对应的指针变为log.txt的文件结构体指针,而2号文件描述符对应的指针同理
在这里插入图片描述
这是另一种用法,把一号文件描述符所对应的指针变为log.txt的文件结构体指针,2号文件描述符所对应的指针变为err.txt文件结构体指针
当我们真正要改变进程对应描述符表中特定下标的指向时,我们也可以使用函数
在这里插入图片描述
在这里插入图片描述
它的用法需要特别注意,不要搞反了,前半句的英语大致意思是,使新的fd变成旧的fd的拷贝,也就是说会有一个fd被覆盖,那我们可以明白newfd应该是你想要被修改的fd,实际上这个函数的本质就是数组对应下标的内容进行拷贝
在这里插入图片描述

在这里插入图片描述

6.输出缓冲区

C库会结合一定的刷新策略,将我们缓冲区中的数据写入给OS( write(FILE->fd,xxxxx) )
①无缓冲区 ②行缓冲区 ③全缓冲区
a.显示器采用的刷新策略:行缓冲。普通文件采用的刷新策略:全缓冲
b.缓冲区节省调用者的时间
c.在你进行fopen打开文件的时候,你会得到FILE结构体指针,缓冲区就在这个结构体中
d.当我们关闭文件的时候,C要帮我们进行冲刷缓冲区
e.在struct file里也有一个文件缓冲区,OS有自己的刷新策略,是不可见的且极其复杂
f.一共其实至少会有三次数据拷贝,从用户到语言,再从语言到struct file,再从struct file到磁盘
其中强制刷新struct file的缓冲区可以使用fsync函数

🌸🌸基础IO(一)的知识大概就讲到这里啦,博主后续会继续更新更多Linux的相关知识,干货满满,如果觉得博主写的还不错的话,希望各位小伙伴不要吝啬手中的三连哦!你们的支持是博主坚持创作的动力!💪💪

评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

轩情吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值