File IO

server/2024/10/19 2:20:00/

Unix标准为程序员提供了一系列的通用IO(无缓冲IO)接口以实现文件读写操作,原书第三章主要所涉及到的系统接口主要针对普通文件为操作目标。通用IO相比于标准IO的最大的区别在于没有缓冲机制,只要调用一次标准IO,就进行IO,而不是像标准IO一样具有缓冲的特点,通用IO的可移植性稍逊色于标准IO (Unix和Windows各有其通用IO接口,但标准IO接口一致)
在开始介绍这些系统接口之前,需要先了解一下Unix环境中对于打开的文件是如何管理的

文件共享

Unix中支持多个进程共享同一个文件,也就是说2个独立的进程打开同一份文件互不影响(在不加文件锁的情况下),但是这仅限于打开文件,对于文件的读写是会有一定的影响的。Unix对打开的文件通过如下三种内核数据结构实现管理。

  • 文件描述符表:每一个进程都会维护一张私有的文件描述符表,文件描述符表中记录了进程已经打开的文件,每一个表项由文件描述符标识和文件指针构成,其中文件指针指向内核文件表项
  • 文件表项:文件表项是内核为维护每一个进程打开的文件所对应的文件状态信息而定义的一个结构,每一个文件表项由文件状态标识、当前偏移量、v节点指针,文件状态标识保存了对应进程对文件的读写权限信息,偏移量保存对应进程在文件中的’‘光标’'位置
  • v节点: v节点是真正意义上的已打开文件的唯一标识,v节点是文件打开时从磁盘读入内存的,其中最重要的信息就是i节点,i节点保存了文件的各种属性信息,包括文件的磁盘地址 (Linux直接用i节点替代v节点)

多进程打开同一份文件时,文件描述符表各个进程独有一份,文件表项与进程一一对应,但是v节点全局只有一份;文件表项与v节点是多对一的关系
在这里插入图片描述
在这里插入图片描述

系统API

open / openat /close

  • open打开相应文件并返回对应文件描述符,通过cmd参数设置打开方式,不定参数用于当cmd中含O_CREAT时新文件的初始权限
  • openat用于在指定的目录下打开文件,其余参数与open类似,openat可以改变目标文件的相对路径(open中如果使用相对路径只能时当前路径或上一级路径),在使用openat之前必须使用open打开一个目录文件获得其文件描述符
  • close关闭打开的文件

在这里插入图片描述
在这里插入图片描述

== 下述给出常见的文件打开方式

  1. 只读 O_RDONLY
  2. 只写 O_WRONLY
  3. 读写 O_RDWR
  4. 不存在则创建 O_CREAT
  5. 追加 O_APPEND
  6. 打开目录 O_DIRECTORY
  7. 重写 O_TRUNC
    通过按位或实现多个打开方式的整合,但请不要把冲突的打开方式一起设置(不能只读且只写),更详细的打开方式宏可以参见附录 ==

eg:

#define pi(x) printf("%ld\n",(long int)x)int fd=open("file",O_CREAT|O_RDWR,0666);//file以工作目录为起点检索pi(fd);close(fd);fd=open("dir",__O_DIRECTORY);int _fd=openat(fd,"file",O_CREAT,0666);//file以dir目录为起点检索close(_fd);close(fd);

在这里插入图片描述
creat: 以只写方式创建一个文件,是历史遗留物,现在一般不用,可以被open完全代替
在这里插入图片描述
在这里插入图片描述

read

从文件中读取字节长度(从光标处开始读取),具体内容存入用户缓冲区,返回值为实际读取到个字节数,一般返回值等于指定值,除非已经读到文件末尾(更多情况参见附录)
在这里插入图片描述

write

从用户缓冲区中写书指定长度字节到文件,返回值为实际写入的个数
在这里插入图片描述
eg:

	char buf[32]={0};pi(read(STDIN_FILENO,buf,sizeof buf -1));//从标准输入读取sizeof buf -1字节//! 一定要-1,预留用户缓冲区结束的标识\0//! 否则后续回显会出现乱码pi(write(STDOUT_FILENO,buf,strlen(buf)));//写回标准输出strlen(buf)字节

在这里插入图片描述

lseek

移动进程在文件处的光标位置,并返回处理后的相对于文件开头偏移量
在这里插入图片描述
whence为三个宏常量

  • 文件开始SEEK_SET
  • 当前位置SEEK_CUR
  • 文件末尾SEEK_END
    offset尾相对于whence的偏移量,其值可正可负
    当whence为SEEK_SET是offset不可为负,为负数判定为0

文件空洞:

当lseek把文件光标设置到文件末尾后正数位置时,函数不会出错,但是会在中间产生一段空白区域,这个区域成为文件空洞,空洞区域以\0填充,系统并不会为这些空洞区域分配具体的磁盘空间,但是使用ls命令时还是会计算空洞字符

	int fd1=open("nohole",O_CREAT|O_RDWR,0666);write(fd1,"hello",5);close(fd1);int fd2=open("hole",O_CREAT|O_RDWR,0666);lseek(fd2,30,SEEK_END);write(fd2,"hello",5);close(fd2);

通过ls -l命令查看文件的属性(30个空洞字符被计算)
在这里插入图片描述
通过od -c命令以字符形式显示文件内容(空洞字符为\0)
在这里插入图片描述
通过du -s命令查看文件实际分配到的磁盘块数(为了效果更明显,此处创建一个足够大的空洞文件)

在这里插入图片描述
在这里插入图片描述
两个文件所分配到的磁盘块数一致,这也说明了空洞区域不会被分配盘块

如果完整的拷贝空洞文件,那么空洞字符也会被拷贝并且分配盘块
在这里插入图片描述

pread / pwrite

如果多个进程对文件的同一片预取进行读写操作(都是读除外),就容易出现数据不一致的情况,这种现象涉及到了进程调度的问题,为了保证读写的原子性,Unix标准也提供了带有原子性的读写API,pread和pwrite,其使用方法与read和write类似,只不过多了从什么位置开始
在这里插入图片描述

dup / dup2

Unix允许进程文件描述符表中存在指向相同文件的文件描述符,这些文件描述符指向相同的文件表项,它们共享文件状态标识和偏移量
在这里插入图片描述

  • dup 返回一个指向文件表项与参数fd相同的新文件描述符
  • dup2 用于文件描述符重定位,将fd2指向fd,会先关闭fd2指向的原文件(dup2具有原子性)

dup图示
在这里插入图片描述
在这里插入图片描述

fcntl

在这里插入图片描述

fcntl有五大功能,具体下述:

  • 复制文件描述符F_DUPFD
  • 获取/改变文件描述符F_GETFD/F_SETFD
  • 获取/改变文件属性F_GETFL/F_SETFL
  • 获取/设置同步异步权F_GETOWN/F_SETOWN
  • 获取/设置文件锁F_GETLK/F_SETLK

其中最为常用的是通过fcntl获取与设置文件属性
eg:

	int fd=creat("file",0666);int flag=fcntl(fd,F_GETFL);//获取文件当前打开属性if(flag&O_ACCMODE==O_WRONLY) printf("write only\n");//判断是否为只写//对于判断只读、只写、读写时需要按位与O_ACCMODE,其他属性判断不需要fcntl(fd,F_SETFL,O_RDONLY)//将文件打开属性变更为只读//!设置之后会关掉原有的只读属性//!如果是增加一个属性,需要使用按位或连接

对于fcntl的其他功能在后续章节会详细讨论,附录中摘录了这些宏的具体描述

附录

图片均来自原著

文件共享:

在这里插入图片描述

打开方式

在这里插入图片描述
在这里插入图片描述

read

在这里插入图片描述

IO效率

IO原则:单次IO尽可能的大,IO的次数尽可能小
在这里插入图片描述

原子操作

在这里插入图片描述

fcntl

在这里插入图片描述


在这里插入图片描述

/dev/fd

在这里插入图片描述


http://www.ppmy.cn/server/131663.html

相关文章

finebi面试题精选

‌‌FineBI‌是由‌帆软软件有限公司开发的一款商业智能(Business Intelligence)产品,旨在通过最终业务用户自主分析企业已有的信息化数据,帮助企业发现并解决存在的问题,及时调整策略以做出更好的决策,从而…

Adobe Photoshop Lightroom(图像处理软件) v8.0 中文版

Adobe Photoshop Lightroom 是由 Adobe 公司推出的一个专业的图像处理软件,主要用于数字摄影后期处理。Lightroom 与 Adobe Photoshop 不同,它是专门为数字摄影而设计的软件,注重于整个摄影工作流程的管理和处理,能够帮助摄影师更…

Go语言学习第一章

1、搭建Go开发环境-安装和配置SDK 基本介绍: SDK的全称(Software Development Kit软件开发工具包) SDK是提供给开发人员使用的,其中包含了对应开发语言的工具包 2、SDK下载 Go语言的官网为:golang.org,无法…

关于京东商品数据采集||附电商API接口采集文档

京东商品数据采集可以通过多种方法实现,包括使用自动化工具、编写爬虫程序、利用API接口等。以下是一些常见的采集方法和注意事项: 1. **使用自动化工具**:可以使用自动化工具进行数据采集。这些工具通常提供图形化界面,用户可以…

Python网络爬虫:分析淘宝商品热度与销量

Python网络爬虫:分析淘宝商品热度与销量 在这篇博客中,我们将深入探讨如何使用Python编写一个网络爬虫,用于分析淘宝商品的买卖热度、销量以及统计热点关键词。我们将使用Python的requests库进行HTTP请求,BeautifulSoup库解析HTM…

遍历有向图链路(DFS算法)- 优化版

在上一节基础上,去除了节点的pre集合,只保留节点next的结合,对数据模型进行了优化,实现思想做了优化。 有向图示例: 基本思路 构建有向图数据模型校验有向图不能出现回路,即当前节点不能出现在历史链路中首…

美团Java一面

美团Java一面 9.24一面,已经寄了 收到的第一个面试,表现很不好 spring bean生命周期 作用域(忘完了) 为什么用redis缓存 redis和数据库的缓存一致性问题 redis集群下缓存更新不一致问题 aop说一下 arraylist和linkedlist 数据库的…

3D看车如何实现?有哪些功能特点和优势?

3D看车是一种创新的汽车展示方式,它利用三维建模和虚拟现实技术,将汽车以更真实、更立体的形式呈现在消费者面前。 一、3D看车的实现方式 1、三维建模: 通过三维建模技术,按照1:1的比例还原汽车外观,包括车身线条、细…