您当前的位置: 首页 > 

风间琉璃•

暂无认证

  • 3浏览

    0关注

    337博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

文件I/O基础

风间琉璃• 发布时间:2022-05-01 20:12:09 ,浏览量:3

一个通用的 IO 模型通常包括打开文件、读写文件、关闭文件这些基本操作, 主要涉及到 4 个函数: open()、 read()、 write()以及 close()。  

一、文件描述符

调用 open 函数会有一个返回值,返回int 类型的数据。在 open函数执行成功的情况下, 会返回一个非负整数, 该返回值为一个文件描述符(file descriptor) , 这说明文件描述符是一个非负整数; 对于 Linux 内核而言,所有打开的文件都会通过文件描述符进行索引。

当调用 open 函数打开一个现有文件或创建一个新文件时,内核会向进程返回一个文件描述符, 用于指代被打开的文件,所有执行 IO 操作的系统调用都是通过文件描述符来索引到对应的文件。

对于一个进程来说,文件描述符是一种有限资源, 文件描述符是从 0 开始分配的,譬如说进程中第一个被打开的文件对应的文件描述符是 0、第二个文件是 1、第三个文件是 2、第 4 个文件是 3……以此类推,文件描述符数字最大值为 1023(0~1023)。每一个被打开的文件在同一个进程中都有一个唯一的文件描述符,不会重复,如果文件被关闭后,它对应的文件描述符将会被释放,那么这个文件描述符将可以再次分配给其它打开的文件、与对应的文件绑定起来。

但是,当我们在程序中,调用 open 函数打开文件的时候,分配的文件描述符一般都是从 3 开始,因为0、 1、 2 这三个文件描述符已经默认被系统占用,分别分配给系统标准输入(0)、 标准输出(1)以及标准错误(2)。

注:Linux 系统下,一切皆文件,也包括各种硬件设备,使用 open 函数打开任何文件成功情况下便会返回对应的文件描述符 fd。每一个硬件设备都会对应于 Linux 系统下的某一个文件,把这类文件称为设备文件。所以设备文件对应的是某一硬件设备,应用程序通过对设备文件进行读写等操作、来使用、操控硬件设备,如 LCD 显示器、串口、音频。

标准输入是键盘,0 :打开键盘对应的设备文件时所得到的文件描述符;标准输出是 LCD 显器,1 :打开 LCD 设备对应的设备文件时所得到的文件描述符;而标准错误: LCD 显示器。

二、open()

在 Linux 系统中要操作一个文件,需要先打开该文件,得到文件描述符,然后再对文件进行相应的读写操作,最后在关闭该文件; open 函数用于打开文件,并且也可以创建一个新的文件。

#include 
#include 
#include 

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

pathname:用于标识需要打开或创建的文件,可以包含路径信息。 flags:调用 open 函数时需要提供的标志, 包括文件访问模式标志以及其它文件相关标志

mode:只有使用 O_CREAT 或 O_TMPFILE 标志时才有效,用于指定新文件的访问权限  

 

标志用途说明O_RDONLY以只读方式打开文件O_WRONLY以只写方式打开文件O_RDWR以可读可写的方式打开文件

前三个是文件访问权限标志,

必须包含其中一种,并且只能是一种

O_CREAT文件不存在,则创建此文件需要传入第3个参数mode,用于指定新文件的访问权限  O_DIRECTORYpathname不为目录,则调用失败O_EXCL用于创建文件O_NOFOLLOWpathname指向符号连接,将不对其解引用,返回错误

注:除了前三种标志,可以通过位或运算(|)将多个标志进行组合。  

mode 参数的类型是 mode_t,为u32 无符号整形数据,权限表示方法如下所示:

O---其他用户的权限 G---同组用户(group)的权限,即与文件所有者有相同组 ID 的所有用户 U---文件所属用户的权限,即文件或目录的所属者 S---文件的特殊权限,文件特殊权限一般用的比较少

3 个 bit 位中,按照 rwx 顺序来分配权限位(特殊权限除外) 。最高位(权值为 4)表示读权限,为 1 时表示具有读权限,为 0 时没有读权限;中间位(权值为 2)表示写权限,为 1 时表示具有 写权限,为 0 时没有写权限;最低位(权值为 1)表示执行权限,为 1 时表示具有可执行权限,为 0 时没有执行权限。

111000000:表示文件所属者具有读、写、执行权限,同组用户和其他用户不具有任何权限

100100100:表示文件所属者、同组用户以及其他用户都具有读权限,但没有写、执行限

文件权限宏定义:

 三、write()

调用 write 函数可向打开的文件写入数据

#include 
ssize_t write(int fd, const void *buf, size_t count);

fd:将进行写操作的文件所对应的文件描述符传递给 write 函数

buf: 指定写入数据对应的缓冲区 count: 指定写入的字节数 返回值: 如果成功将返回写入的字节数(0 表示未写入任何字节)

注意:读写操作都是从文件的当前位置偏移量处开始。默认情况下当前位置偏移量一般是 0,指向了文件起始位置,当调用 read、 write 函数读写操作完成之后, 当前位置偏移量也会向后移动对应字节数。

四、read()

调用 read 函数可从打开的文件中读取数据

#include 
ssize_t read(int fd, void *buf, size_t count);

fd: 文件描述符 buf: 指定用于存储读取数据的缓冲区

count: 指定需要读取的字节数

返回值: 如果读取成功将返回读取到的字节数

 五、close()

调用 close 函数关闭一个已经打开的文件

#include 
int close(int fd);

fd: 文件描述符,需要关闭的文件所对应的文件描述符 返回值: 如果成功返回 0,如果失败则返回-1

六、lseek() 

对于每个打开的文件, 系统都会记录它的读写位置偏移量,把读写位置偏移量称为读写偏移量,记录了文件当前的读写位置,当调用 read()或 write()函数对文件进行读写操作时,就会从当前读写位置偏移量开始进行数据读写。

读写偏移量用于指示 read()或 write()函数操作时文件的起始位置,会以相对于文件头部的位置偏移量来表示,文件第一个字节数据的位置偏移量为 0。

#include 
#include 
off_t lseek(int fd, off_t offset, int whence);

fd: 文件描述符。 offset: 偏移量,以字节为单位。 whence: 用于定义参数 offset 偏移量对应的参考值,如下:

1.SEEK_SET:读写偏移量将指向 offset 字节位置处(从文件头部开始算)

2.SEEK_CUR:读写偏移量将指向当前位置偏移量 + offset 字节位置处,

3.SEEK_END:读写偏移量将指向 文件末尾 + offset 字节位置处

返回值: 成功将返回从文件头部开始算起的位置偏移量(字节为单位), 当前的读写位置  

 

关注
打赏
1665385461
查看更多评论
立即登录/注册

微信扫码登录

0.1249s