Linux下的IO操作以及ext系列文件系统

文件描述符

0、1和2

系统在开启后,会默认打开三个流,stdin、stdout、stderror,后面打开文件会从文件描述符表中挑选一个最小的空闲描述符来使

文件描述符表

在task_struct中,有一个指针,指向一个file_struct,其中最重要的部分就是一个指针数组,每个指针都是指向打开文件的指针,

所谓文件描述符fd,其实就是这个指针在这个数组当中的下标。所以当打开一个文件描述符但是不关闭时,会导致文件描述符泄露

重定向

  • 基于上面对文件描述符和分配方式的介绍,不难发现,其实操作系统就是根据文件描述符表中每个指针对文件进行操作,所以更改
    文件描述符表的内容,就可以实现重定向
cpp 复制代码
close(1);
int fd = open("log.txt", O_RDWR|O_APPEND);
printf("hello world\n");

这时,上述代码不再往屏幕上打印,发现打印到log.txt当中,因为系统默认标准输出的文件描述符是1,而我们用log.txt的文件指

针替换了标准输出的位置,操作系统继续默认往文件描述符表的一号位置操作,就实现了往log.txt输出内容的重定向操作

  • 系统调用dup2
cpp 复制代码
int dup2(int oldfd, int newfd);

oldfd表示原来的文件描述符,newfd表示目的要替换的文件描述符

FILE* 文件流指针

其实就是struct_IO_FILE的重定义,指向了一个struct_IO_FILE结构体,其中包含了file_no,和文件描述符是对应的,换言之,FILE* 是对文件描述符的封装

Linux下一切皆文件

这句话其实在源自于Linux对驱动程序的处理原则。驱动程序+硬件,才让一个硬件能够使用。对于普通文件,单开一个文件后,在内

核中会创建一个struct file,保存着文件的inode元信息,其中保存着一个struct file_operation指针,指向一个struct file_operation结构体,其中包含许多函数指针,他们对于硬件来说,就指向硬件的驱动程序,将对硬件的控制权交给函数处理,所以对于上

层来说,对于硬件、软件的操作,其实都是对于文件的操作,几乎Linux的所有资源,都能够通过操作文件时使用的系统调用read、write来使用

缓冲区

  • 当需要对硬件操作时,需要cpu从用户态切换到内核态,完成上下文切换,频繁的使用系统调用对硬件进行操作,会降低cpu的运行
    效率,所以需要缓冲区集中的对数据进行操作,根据输入输出的不同分为输入缓冲区和输出缓冲区,他们都是内存中的一块区域

缓冲区类型

  1. 全缓冲区:只有打满时才进行io操作,对磁盘文件的操作一般使用全缓冲区
cpp 复制代码
close(1);
int fd = open("log.txt", O_TRUNC | O_CREAT | O_RDWR);
dup2(fd, 1);
printf("hello world\n");

可以发现并没有实际的写入文件,因为原来的对标准输出的操作转换为了对磁盘的操作,采取全缓冲的方式。显然我们并没有写满缓

冲区

  1. 行缓冲区:涉及到终端的操作,比如像屏幕上打印,输入字符串,都是采取的行缓冲区,遇到换行符时刷新缓冲区

  2. 无缓冲区:不缓冲,直接进行输入输出,比如stderr,为了尽快显示错误信息,操作直接输出不缓冲的方式

刷新时机

  1. 进程结束
  2. 系统调用fflush
  3. 换行符

用户级缓冲区和内核级缓冲区

  • 看下面的代码
cpp 复制代码
const char* msg1 = "hello fwrite\n";
const char* msg2 = "hello write\n";
printf("hello printf\n");
fwrite(msg1, strlen(msg1), 1, stdout);
write(1, msg2, strlen(msg2));
fork();

将上面的代码重定向到文件后,可以发现,除了write,每句都打印了两遍

  1. printf和fwrite是标准库对系统调用的封装,即最后还是调用了write,但是他加上了自己的缓冲区,这种语言级的缓冲区不是系
    统的缓冲区。向屏幕输出时,采用行缓冲;但是重定向到文件之后,采取全缓冲,显然我们没有打满缓冲区,所以fork之后的子进程
    同样获得了缓冲区,两者结束时进行刷新,所以printf和fwrite写入了两次
  2. 对于write,是系统调用,使用的是系统的缓冲区,采取行缓冲,在fork之前已经刷新完毕,所以只有一次write,并且write在printf和fwrite之前

ext文件系统

ext2是较早的版本,ext3、ext4均是在ext2的改进,核心设计并没有发生改变。

cpp 复制代码
//MBR Partition1 Partition2 Partition3...
//    /        \
// Boot Block   ext2 File System
//               /             \
//    Block Group1   Block Group2...
//                   /          \
//   Super Block   GDT   Block Bitmap   inode Bitmap   inode table   block table

Boot Block

是一个分区中任何一个文件系统都没有权利修改的分区,存放着系统启动相关信息,一旦破坏,基本上就无法正常启动使用相关分区

或者文件系统的操作系如同了

Block Gruop 块组

ext2文件系统有多个块组组成

Super Block 超级块

是整个文件系统相关信息的描述,包括block大小、inode大小、已使用和未使用的inode数目、已使用和未使用的block数目、最后一

次读写时间等等

可以说,一旦超级块被破坏,这个文件系统就报废了。

所以,文件系统会在第一个块组的开头放置一个超级块的备份(至于其他分区开头是否备份没有硬性要求),以保证在硬盘保存超级

块的区域受损后文件系统依然能够正常使用

GDB 块组描述符表

group desctiption table,描述这个块组的信息,比如inode数目,block bitmap、inode bitmap、inode table、block table的起

止位置等等

块组描述符表的数目,与文件系统中块组的数目相同,每个块组的起始位置也会保存一份GDB的拷贝

两个bitmap和table

bitmap用来表示相应的table中的相应存储位置是否被占用,真正的内容存储在table中,bitmap起到辅助检索的作用

创建一个文件的过程

目录和文件的区别

在linux下,两者没有本质区别,目录其实也是存储在文件系统中的文件,或者换句话说,linux中没有目录只有文件。目录在block

中存储了

其中包含的所有文件和目录的名称,在inode中保存了文件名和inode的映射关系,这样就可以通过文件名获得inode,从而获得访问

目标文件

所需要的信息了

  1. 首先查找到空闲的block和inode,存储数据到block,存储文件信息到inode
  2. 更新所在目录的inode信息,更新文件名和inode的映射关系

软硬连接

硬链接

硬链接其实建立的是相同的inode和文件的映射关系,每建立一个硬链接,硬连接数就+1,当文件删除时,先将硬连接数-1

如果减为零,就将文件删除。所以硬链接可以用于文件的备份

软连接

软连接是通过名字引用另一个文件,软连接文件和被链接文件是两个文件,类似于桌面快捷方式

linux中两个进程打开同一个文件

  1. 文件描述符:对于同一个文件,两个进程产生的文件描述符是两个文件描述符,因为这本质上是指向file_operation结构体的指针在文件描述符表当中的数组下标
  2. 一个进程删除文件时,另一个进程并不会立刻读写失败,删除文件是操作的目录项,而另一个进程已经拥有了这个文件的inode信息,能够找到磁盘上的目标文件,所以不会立刻读写失败
  3. 一个进程修改文件时,另一个进程是可以立刻感知的,因为修改文件是对磁盘文件本身进行的操作
相关推荐
打工哪有不疯的2 小时前
使用 MSYS2 为 Qt (MinGW 32/64位) 完美配置 OpenSSL
c++·qt
HypoxiaDream2 小时前
LINUX-Ext系列⽂件系统
linux·运维·服务器
小毛驴8502 小时前
Linux curl 命令用法
linux·运维·chrome
李斯啦果2 小时前
【Linux】Linux目录配置
linux·运维·服务器
AI+程序员在路上2 小时前
linux下线程中pthread_detach与pthread_join区别
linux·运维·服务器
代码游侠2 小时前
C语言核心概念复习——C语言基础阶段
linux·开发语言·c++·学习
logocode_li2 小时前
说透 Linux Shell:命令与语法的底层执行逻辑
linux·运维·ssh
CHENKONG_CK2 小时前
晨控CK-LR08-E00与汇川H5U系列PLC配置MODBUSTCP通讯连接手册
linux·服务器·网络
㓗冽2 小时前
60题之内难题分析
开发语言·c++·算法