【Linux】缓冲区再理解

文章目录

  • 一、标准流
  • 二、linux系统提供操作系统调用接口
    • 1. open创建文件
    • 2. write写入
    • 3. read读入
  • 三、文件描述符
    • 1. 由来
    • 2. 文件描述符分配规则
    • 3. 输出重定向
    • 4. dup输出重定向
  • 四、缓冲区

一、标准流

c语言程序运行起来就默认打开3个流

标准输出流 - stdout(屏幕打印,这里屏幕就是编译器调试控制台)

标准输入流 - stdin(键盘)

标准错误流 - stderr

这几个流类型都是FILE*

fputs向一般文件(磁盘)或者硬件进行写入

#include 

int main()
{
  const char* s = "hello world\n";
  fputs(s, stdout);

  return 0;
}

【Linux】缓冲区再理解_第1张图片


【Linux】缓冲区再理解_第2张图片

stderr也是可以输出到屏幕上的

但重定向输出到txt文件中就什么都没有,因为> 是输出重定向的符号

./test > test.txt 2>&1
    //原本1指向显示器,重定向指向文件,再将2拷贝到1里面,2也指向文件了

二、linux系统提供操作系统调用接口

打开

【Linux】缓冲区再理解_第3张图片

关闭

【Linux】缓冲区再理解_第4张图片

#include 
#include 
#include 
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
       //打开文件的文件名  以读、写等方式打开 以什么模式(权限)    //返回文件描述符,   错误返回-1
int creat(const char *pathname, mode_t mode);

#include 
int close(int fd);

1. open创建文件

open的返回值是操作系统给予的,实际上是操作系统内部一个数组的下标

#include 
#include 
#include 
#include 
#include 


int main()
{
  int fd = open("./test.txt", O_WRONLY | O_CREAT, 0644);
  close(fd);

  return 0;
}

【Linux】缓冲区再理解_第5张图片

标志位只有一个bit位为1

【Linux】缓冲区再理解_第6张图片

【Linux】缓冲区再理解_第7张图片


2. write写入

不需要写入\0,只是c中的结束标志,写入文件不需要

【Linux】缓冲区再理解_第8张图片

#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
  int fd = open("./test.txt", O_WRONLY | O_CREAT, 0644);
  if(fd < 0)
  {
    perror("error");
    return 1;
  }
  

  const char* s = "hello world\n";
  int n = 5;
  while(n--)
  {
    write(fd, s, strlen(s));
  }
  
  close(fd);

  return 0;
}

【Linux】缓冲区再理解_第9张图片


3. read读入

  • 返回值是有效长度,0的话停止

【Linux】缓冲区再理解_第10张图片

#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
  int fd = open("./test.txt", O_RDONLY, 0644);
  if(fd < 0)
  {
    perror("error");
    return 1;
  }
  

  char buffer[128];
  ssize_t rs = read(fd, buffer, sizeof(buffer) - 1);
  if(rs > 0)
  {
    buffer[rs] = 0;
    printf("%s\n", buffer);
  }
  


  close(fd);

  return 0;
}

【Linux】缓冲区再理解_第11张图片


三、文件描述符

1. 由来

之前所学的所有的文件操作:对文件内容操作,对文件的属性操作

如果一个文件,没有被打开,这个文件在磁盘
如果我创建一个空文件,该文件也占磁盘空间
文件有属性,属性也是数据。
磁盘文件=文件内容+文件属性(struct file{}描述)

而一个进程可以打开多个文件:

struct task_struct{ 
    
    struct file_struct* p;
}
//p指向这个结构体
struct file_struct{
        //里面有个数组
    struct file* fd_array[];
    //0、1、2,对应stdin,stdout,stderror
    //这里的数组下标对应的就是fd文件描述符
}
//描述每个文件
struct file
{
    //文件属性
    fd;
    //.......
    //读写操作,函数指针
    int(*read)();
    int(*write)();
}

标准:

#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
  printf("stdin: %d\n", stdin->_fileno);
  printf("stdout: %d\n", stdout->_fileno);
  printf("stderr: %d\n", stderr->_fileno);

  return 0;
}

【Linux】缓冲区再理解_第12张图片


2. 文件描述符分配规则

给新文件分配的fd,是从fd_ array中找一个下标最小的,没有被使用的,作为新的fd

close(0);
//再open会获得0

3. 输出重定向

struct file
{
    //存储着fd文件描述符
}

当遇到

close(1);

后面再打开一个文件会将该文件的指针存在下标为0的文件描述数组里

当一些语言层的read等调用时候,获取了fd,只往fd对应的文件里面进行操作

#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
  close(1);
  int fd = open("./test.txt", O_CREAT | O_WRONLY, 0644);
  printf("hello world\n");

  return 0;
}

【Linux】缓冲区再理解_第13张图片

本应该输出再屏幕上的输出到了文件中


4. dup输出重定向

【Linux】缓冲区再理解_第14张图片

//输出重定向
dup2(fd, 1);

四、缓冲区

close(fd)之后结果发生了变化,close之后不会重定向卸载txt文件

#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
  close(1);
  int fd = open("./test.txt", O_CREAT | O_WRONLY, 0644);
  printf("hello world\n");
  //close(fd);
  return 0;
}

【Linux】缓冲区再理解_第15张图片

原因是c语言也有缓冲区

【Linux】缓冲区再理解_第16张图片

进程退出file会刷新内容到OS缓冲区,但如果没有fd就不知道是哪个文件

当close(fd)时候,fd关闭,无法访问无法刷新

  • 解决:可以在close前加上flush(stdout);

回忆:为什么要有缓冲区?

因为磁盘读取的速度远远低于cpu,cpu不可能进行长时间等待,等待过程中可以进行其他运算并且放到缓冲区进行等待

普通文件是全缓冲,屏幕是行刷新(遇到\n刷新)

关闭文件时候,OS缓冲区会直接刷新到磁盘

c提供的接口运行后都放在c缓冲区


你可能感兴趣的:(Linux,缓冲区,linux,IO流)