以下是关于Linux文件IO的介绍和基本使用,希望对您有所帮助。
如果我的文章让你感兴趣,可以点赞收藏关注一波。
目录
1.文件的概念
- “一切皆是文件”是 Unix/Linux 的基本哲学之一。不仅普通的文件,目录、字符设备、块设备、套接字等在 Unix/Linux 中都是以文件被对待;它们虽然类型不同,但是对其提供的却是同一套操作界面。——《Linux内核设计与实现》
- 文件=文件内容+文件属性(创建一个新文件也是占空间的),VFS使得可以通过使用同一套文件 I/O 系统调用即可对 Linux 中的任意文件进行操作而无需考虑其所在的具体文件系统格式,正是有了VFS的存在,Unix/Linux中的“一切皆是文件”的口号才能够得以实现。
- 平时所理解的文件,指普通的文本文件。
- linux “一切皆是文件”,指的是除了普通文件外,几乎所有可操作的设备或接口都可视为文件。
Linux系统中文件的分类
- 普通文件(-)(regular):最常使用的一类文件,按照其内部结构又可分为纯文本文件(ASCII)、二进制文件(binary)、数据格式的文件(data)、各种压缩文件。
- 目录文件(d)(directory):用于存放文件名以及其相关信息的文件,是内核组织文件系统的基本节点。
- 管道文件(p)(pipe):用于不同进程的信息传递。
- 套接字文件(s)(socket):通常用在网络数据连接。
- 链接文件(l)(link):指向一个真实存在的文件链接,类似于Windows下的快捷方式。
- 字符设备文件(c)(character):串行端口的接口设备,例如键盘、鼠标等等。
- 块设备文件(b)(block):存储数据以供系统存取的接口设备,简单而言就是硬盘。例如一号硬盘的代码是 /dev/hda1等文件。
2.文件IO基础
文件 I/O 指的是对文件的输入/输出操作
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <strings.h>
#define SIZE 1024
int main(void)
{
char buff[SIZE];
bzero(buff,SIZE);
int fd1, fd2;
int ret;
/* 打开源文件 src_file(只读方式) */
fd1 = open("./src_file", O_RDONLY);
if (fd1 == -1)
return fd1;
/* 打开目标文件 dest_file(只写方式) */
fd2 = open("./dest_file", O_WRONLY);
if (fd2 == -1)
{
ret = fd2;
goto out1;
}
/* 读取源文件 1KB 数据到 buff 中 */
ret = read(fd1, buff, SIZE);
if (ret == -1)
goto out2;
/* 将 buff 中的数据写入目标文件 */
ret = write(fd2, buff, SIZE);
if (-1 == ret)
goto out2;
ret = 0;
out2:
/* 关闭目标文件 */
close(fd2);
out1:
/* 关闭源文件 */
close(fd1);
return ret;
}
代码实现的功能是,从源文件 src_file 中读 取 1KB 数据,然后将其写入到目标文件 dest_file 中,此操作分为以下几步:
- 首先调用 open 函数将源文件和目标文件打开
- 调用 read 函数从源文件中 读取 1KB 数据
- 调用 write 函数将这 1KB 数据写入到目标文件中
- 最后调用 close 函数关闭源文件和目标文件
函数表格
下面表格为open、close、read、write函数表格,功能包含头文件、原型、参数以及返回值!
open
close
read、write
2.1 文件描述符
当进程打开现有文件或创建新文件时,内核向进程返回一个文件描述符 fd(file descriptor),文件描述符就是内核为了高效管理已被打开的文件所创建的索引,用来指向被打开的文件,所有执行I/O操作的系统调用都会通过文件描述符来操作此文件。
对于一个进程来说,文件描述符是一种有限资源, 文件描述符是从 0 开始分配的,每一个被打开的文件在同一个进程中都有 一个唯一的文件描述符,不会重复,如果文件被关闭后,它对应的文件描述符将会被释放,那么这个文件描 述符将可以再次分配给其它打开的文件、与对应的文件绑定起来。
文件描述符一般都是从 3 开始,而0、 1、 2 这三个文件描述符默认分配给了系统标准输入(0)、 标准输出(1)以及标准错误(2)
文件描述符本质
一个 Linux 进程启动后,会在内核空间中创建一个 PCB 控制块(包含了一个进程在运行时的所有信息),PCB 内部有一个文件描述符表(File descriptor table),记录着当前进程所有可用的文件描述符,也即当前进程所有打开的文件。
除了文件描述符表,系统还需要维护另外两张表:
打开文件表(Open file table)
i-node 表(i-node table)
打开文件表存储了以下信息:
- 文件偏移量
- 状态标志,比如只读模式、读写模式、追加模式、覆盖模式等
- i-node 表指针
i-node 表包含了以下的信息:
- 文件类型,例如常规文件、套接字或 FIFO。
- 文件大小
- 时间戳
- 文件锁
由此可知:
- 同一个进程的不同文件描述符可以指向同一个文件
- 不同进程可以拥有相同的文件描述符
- 不同进程的同一个文件描述符可以指向不同的文件(除了 0、1、2 这三个特殊的文件)
- 不同进程的不同文件描述符也可以指向同一个文件
一个进程可以打开多个文件, 但是在 Linux 系统中,一个进程可以打开的文件数是有限制,打开的文件是需要占用内存资源的,文件越大、打开的文 件越多那占用的内存就越多,必然会对整个系统造成很大的影响,如果超过进程可打开的最大文件数限制, 内核将会发送警告信号给对应的进程,然后结束进程。