赞
踩
目录
相关博客详细介绍:Linux应用开发基础知识——文件IO操作(三)_linux应用开发文件io-CSDN博客
IO操作,即输入/输出操作,是指在计算机系统中数据在内存和外围设备之间传输的行为。在操作系统的上下文中,IO通常关联于文件系统的操作,以及与外设如硬盘、显示器、网络接口和键盘鼠标等的交互。
文件IO(File I/O)
- 读取(Read): 从文件系统中的文件读取数据到内存中。
- 写入(Write): 将数据从内存写入到文件系统的文件中。
- 打开(Open): 打开文件以便读取或写入数据。
- 关闭(Close): 完成文件操作后关闭文件,释放资源。
- 定位(Seek): 移动文件内的指针到特定位置,用于读写操作。
- 同步(Sync): 确保内存中的数据与存储设备中的数据同步。
设备IO(Device I/O)
- 直接IO: 与具体的硬件设备进行数据传输,如磁盘、GPU等。
- 缓冲IO: 数据首先被读取到一个内存缓冲区,然后再从缓冲区移动到最终的目的地。
- 同步与异步IO: 同步IO要求操作完成后程序才继续运行,而异步IO允许程序在操作还在进行时继续其他任务。
在Unix和Unix-like操作系统(比如Linux)中,根目录(表示为/
)是文件系统结构的最高级别。根目录下有一系列的标准子目录,虽然这些可能会根据不同的发行版有所差异,但大多数系统都遵循以下的结构和用途:
目录 | 用途 |
---|---|
/bin | 存放基本命令和程序,系统启动和修复时需要 |
/boot | 启动相关文件,如内核vmlinuz ,启动加载器GRUB配置文件等 |
/dev | 包含硬件设备文件,如/dev/sda 、/dev/tty |
/etc | 系统配置文件,如启动、服务配置、用户账户设置等 |
/home | 用户主目录,每个用户都有自己的子目录(除了root用户) |
/lib | 系统核心操作和文件操作所需的库文件,如C标准库、设备驱动等 |
/media | 用于挂载可移动媒体,如CD-ROMs、USB驱动器等 |
/mnt | 用于临时挂载文件系统,如网络文件系统NFS |
/opt | 第三方应用程序或额外软件包的安装位置 |
/proc | 虚拟文件系统,映射运行时系统信息,如内存、硬件配置等 |
/root | root用户的主目录 |
/run | 系统运行时信息,如当前登录用户和运行中的服务 |
/sbin | 系统管理命令,通常由系统管理员使用 |
/srv | 服务提供的数据 |
/sys | 虚拟文件系统,包含设备和驱动信息,内核设备树的一部分 |
/tmp | 存储临时文件,系统重启时通常会被清理 |
/usr | 用户安装的应用程序和文件,如/usr/bin 、/usr/sbin 、/usr/local |
/var | 存放经常变化的文件,如日志文件(/var/log ),包和数据库(/var/lib ) |
使用ls -l
命令时,列出的文件和目录会在第一列显示这些符号,从而可以快速识别它们的类型。而file
命令则用于获取文件的具体类型信息,帮助用户更精确地了解文件的性质。
文件类型 | 表示符号 | 描述 |
---|---|---|
普通文件 | - | 包括文本文件、二进制文件和数据文件。 |
目录文件 | d | 用来存储其他文件或目录的容器。 |
链接文件 | l | 硬链接和符号链接(软链接),类似快捷方式,指向其他文件。 |
设备文件 | c , b | c 表示字符设备文件,b 表示块设备文件。 |
管道文件 | p | 命名管道(FIFO),用于进程间通信。 |
套接字文件 | s | 用于进程间的网络通信。 |
特殊文件 | 例如/dev/null ,用于废弃输出或产生空输入的特殊目的文件。 |
标准IO打开的是一个文件指针;
系统IO打开的是一个文件描述符。
3.1.1 标准I/O:
概述:标准I/O是C语言标准库提供的一组函数,它提供了缓冲的I/O操作。这意味着当你使用标准I/O函数(如
fopen
,fprintf
,fread
,fwrite
等)时,数据可能首先被存储在一个中间缓冲区,然后才实际写入磁盘或从磁盘读取。这种缓冲可以提高I/O操作的效率。文件指针:使用标准I/O打开文件时,会返回一个文件指针(通常是
FILE*
类型)。这个文件指针是对打开文件的抽象表示,可以用来访问和操作文件。3.1.2 系统I/O:
概述:系统I/O通常指的是操作系统提供的系统调用(如UNIX/Linux环境中的
open
,read
,write
,close
等)。与标准I/O不同,系统I/O通常是非缓冲的,这意味着每次read
或write
调用都直接与磁盘进行交互,没有中间缓冲区。文件描述符:当使用系统I/O函数打开文件时,会得到一个文件描述符,这是一个整数值,用于标识和访问打开的文件。文件描述符是对打开文件的底层表示,可以用于后续的系统I/O操作。
通用性:系统IO提供了一组非常基础的系统调用,如open
, read
, write
, close
等,这些调用可以用于普通文件、设备文件(如字符设备和块设备)、管道、套接字等。这意味着系统IO对于UNIX和类UNIX操作系统上所有类型的文件描述符都是通用的。
简约性:系统IO调用通常不会在用户空间添加额外的缓冲层。这意味着当你使用read
或write
系统调用时,数据直接从内核缓冲区传输到你的程序缓冲区,或者反过来,没有中间缓冲处理。这个过程是透明的,没有格式化操作,确保了数据的读写是原始和未处理的。
非格式化IO:使用系统IO,数据的读写是非格式化的,即数据被视为原始字节流。程序员负责解释数据的结构和意义。
缓冲处理:标准IO提供了缓冲机制,这可以提高IO操作的效率,因为它减少了程序与内核之间的系统调用次数。然而,这种缓冲处理也增加了复杂性,尤其是在需要处理同步和数据一致性时。
格式化IO:标准IO提供了格式化的输入输出函数,如printf
和scanf
,这些函数可以让你以一定格式读写数据,而无需手动处理数据的序列化和反序列化。
抽象层:标准IO通过FILE
结构体提供了一个文件的高级抽象,这使得读写文件更加简单,但也隐藏了底层细节。
在Unix和类Unix系统中,当一个新的程序开始执行时,系统IO和标准IO都会默认打开三个特殊的文件,这些文件是标准输入(stdin)、标准输出(stdout)和标准错误(stderr)。这三个文件的行为在系统IO和标准IO中是一致的,但它们的表示形式不同。
在系统IO中,这三个文件分别与三个特定的文件描述符相关联:
这些文件描述符是在程序启动时由操作系统自动打开的,并且它们通常连接到终端(也就是命令行界面)。
在使用标准IO时,这三个标准流以流(FILE*)的形式存在:
stdin
stdout
stderr
这些流是标准C库自动提供的,并且已经在程序启动时预定义好了。
对于标准IO,不需要打开这些流;它们已经是打开状态,并且准备好供您的程序使用。对于系统IO,即使这些文件描述符也是预先打开的,仍然可以使用相关的系统调用,如read
和write
,通过这些文件描述符与这些文件进行交云。
标准流 | 系统IO描述符 | 标准IO流 | 默认打开方式 | 默认设备 |
---|---|---|---|---|
标准输入(stdin) | 0 | stdin | 只读 | 键盘 |
标准输出(stdout) | 1 | stdout | 只写 | 屏幕 |
标准错误(stderr) | 2 | stderr | 只写 | 屏幕 |
FILE*
类型的指针,其具体类型在C语言的标准库中定义。空洞文件(Sparse file)是文件系统中的一种文件,其中包含了一定量的未使用的空间,这部分空间在磁盘上不占用物理位置,即使文件的大小看起来很大。这些未使用的空间被称作“空洞”。在大多数文件系统中,当读取文件中的这些空洞时,它们表现得就像读取了一串零。
空洞通常在文件中出现,因为数据被写入到文件的不连续区域。例如,有些程序可能会根据需要将信息设置或写入文件中特定的位置,并跳过文件的其他部分。如果程序在文件的开始处写入数据,然后跳到接近文件末尾的位置继续写入,它之间的部分就形成了空洞。
4.1.1 物理和逻辑大小:空洞文件的逻辑大小(文件的大小,如用ls -l
查看)可能会很大,但它的物理大小(即实际占用的磁盘空间,可以用du
命令查看)可能相当小。
4.1.2 节省空间:空洞文件的优点在于它可以在不实际使用相同数量磁盘空间的情况下创建大文件。这对于某些特定的应用程序来说是非常有用的,例如数据库和虚拟机映像,它们可能需要创建大型文件,但实际上只使用了文件的一小部分。
4.1.3 透明使用:对于操作系统和应用程序,空洞文件的使用是透明的。当程序读取文件中的空洞部分时,文件系统会返回一个数据全零的缓冲区,程序通常无需关心这些零是实际存储在磁盘上还是由空洞生成的。
在Unix和类Unix系统中,可以通过使用lseek
系统调用在文件中创建空洞。例如,一个程序可以打开一个文件,写入一些数据,然后使用lseek
跳过一段距离,再写入更多数据。跳过的部分就会形成一个空洞。
尽管空洞文件节省了空间,但它们也有一些潜在的局限性和缺点:
在Linux中,文件描述符是一个非常小的正整数,用于表示一个打开的文件。每个进程都有一个文件描述符表,用于跟踪打开的文件。
系统调用(如open, read, write, close)提供了操作系统级别的文件IO操作,直接与内核交云,性能较高但使用复杂。
库函数(如fopen, fread, fwrite, fclose)是建立在系统调用之上的封装,提供了更加用户友好的接口,自动处理错误和缓冲。
这些是三个预定义的文件描述符,分别是标准输入(stdin, 0)、标准输出(stdout, 1)和标准错误(stderr, 2),它们默认分别连接到键盘和终端。
open系统调用用于打开一个文件,如果需要也可以创建一个文件,它返回一个文件描述符,用于后续的读写操作。
read用于从一个已打开的文件描述符中读取数据,而write用于向一个已打开的文件描述符写入数据。
文件权限决定了用户对文件的读、写、执行权限,而所有权则指文件属于哪个用户和用户组。
软链接(或称符号链接)类似于Windows的快捷方式,是指向另一个文件的特殊文件。
硬链接是文件系统中另一个指向相同inode的名称,与原始文件无法区分。
inode是文件系统中的一个数据结构,包含了关于文件的元数据,如文件大小、权限、所有权和数据位置等,但不包含文件名。
lseek可以重新定位文件描述符的读写文件偏移,允许随机访问文件中的任何位置。
文件锁定是一种机制,可以防止多个进程同时写入或读写同一个文件,从而避免数据损坏或不一致。
文件IO操作通常在错误时返回特定的值(如-1),并设置errno变量以指示具体错误。程序应该检查IO操作的返回值,并适当地处理错误情况。
这两个调用用于将缓冲的数据写入硬盘,以确保数据的持久化。fsync同时刷新文件的元数据,而fdatasync只刷新文件数据,不包括元数据。
直接IO绕过操作系统的缓冲,直接在应用程序和硬盘之间传输数据,这可以减少延迟并提高大型连续数据传输的性能。
为了处理大文件,应该使用支持64位偏移量的函数(如lseek64),并确保文件系统和操作系统都支持大文件处理。
阻塞IO指的是IO操作会使得进行该操作的进程挂起,直到操作完成。而非阻塞IO则是IO操作会立即返回,不会等待操作完成。
多路复用IO允许一个线程同时监视多个文件描述符,以检查一个或多个文件描述符是否就绪(可读、可写、有错误等)。常见的多路复用IO实现有select, poll, epoll。
mmap允许程序将一个文件或其他对象映射到内存地址空间,这可以提供一种访问文件的高效方法,特别是对于频繁的随机访问。
可以使用stat或fstat系统调用获取文件的状态信息,其中包括文件大小。
同步IO要求发起IO操作的进程等待IO操作完成才能继续执行。异步IO则允许进程继续执行,并在IO操作完成时通过信号、回调或其他机制通知进程。
ioctl是设备独立的系统调用,用来与设备驱动程序进行交互,可以用来执行设备特定的操作,如格式化、设置硬件参数等。
umask是一个进程属性,用于设置默认的文件权限。当创建新文件时,umask会从完全权限中减去,以得到新文件的权限。
这些是open系统调用的标志。O_SYNC用于同步IO,使得每次write都等待数据物理写入磁盘。O_ASYNC使得在文件可读或可写时,操作系统会向进程发送一个信号。
Linux支持多种IO模型,包括阻塞IO、非阻塞IO、IO多路复用、信号驱动IO和异步IO。
可以通过调用posix_fadvise和madvise函数来给操作系统建议如何处理文件或内存映射文件的缓存。
可以使用stat或fstat系统调用并检查返回的结构中的st_mode字段,以确定文件是普通文件、目录、字符设备、块设备还是管道。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。