系统编程-文件系统IO

注意这是我的《Linux-Unix系统编程手册》这个本书的第四章和第五章的笔记

通过的文件IO接口

在Linux中的文件结构都是通用的,这意味这使用几个函数就可以控制系统中的所有文件类型,包括终端

这些通用接口主要是:

1
2
3
4
5
6
open();
write();
read();
lseek();
close();
creat();//由于可以使用open()来打开、创建一个文件,所以这个函数用的少。

还包括一个通用接口以外的函数:ioctl(),ioctl()系统调用又为执行文件和设备操作提供了一种多用途机制。

open()函数

这个函数就是打开一个文件,返回所打开文件的文件描述符。可以使用各种标志位来打开文件。

1
2
3
open()//第一个参数是文件位置,第二个是如何打开文件,第三个是权限。

int dst_fd = open(destination, O_CREAT | O_WRONLY | O_TRUNC, 0644);

read()函数

从指定的文件中读取数据到buffer中,返回所读取的字符个数。

如果 read()调用成功,将返回实际读取的字节数,如果遇到文件结束(EOF)则返回 0
如果出现错误则返回-1ssize_t 数据类型属于有符号的整数类型,用来存放(读取的)字节数或-1(表示错误)。

1
2
3
read()//第一个参数是从哪个文件中读取,第二个是存到哪里去,第三个是一个读取字符的数量。

while((readed = read(STDIN_FILENO, buf, BUF_SIZE)) > 0)

一次 read()调用所读取的字节数可以小于请求的字节数。对于普通文件而言,这有可能是因为当前读取位置靠近文件尾部。当 read()应用于其他文件类型时,比如管道、FIFO、socket 或者终端,在不同环境下也会出现 read()调用读取的字节数小于请求字节数的情况。例如,默认情况下从终端读取字符,一遇到换行符(\n),read()调用就会结束。

write()函数

这个函数参数含义和read()函数意义一致。返回的是读取到的字符个数,注意如果 write()调用成功,将返回实际写入文件的字节数,该返回值可能小于 count 参数值。这被称为“部分写”。对磁盘文件来说,造成“部分写”的原因可能是由于磁盘已满,或是因为进程资源对文件大小的限制。

1
if((w = write(fd, buf + wrote, readed - wrote)) ==-1)

close()函数

关闭文件,成功返回0,反之-1

lseek()函数

改变、获取文件的偏移量。返回现在文件偏移量位置。

1
2
lseek()//第一个参数指定文件,第三个参数是指定位置,第二个参数是指定偏移量
off_t src_size = lseek(src_fd, 0, SEEK_END);

lseek()并不适用于所有类型的文件。不允许将 lseek()应用于管道、FIFO、socket 或者终端。一旦如此,调用将会失败,并将 errno 置为 ESPIPE。另一方面,只要合情合理,也可以将 lseek()应用于设备。例如,在磁盘或者磁带上查找一处具体位置

文件空洞

如果程序的文件偏移量已然跨越了文件结尾,然后再执行 I/O 操作,将会发生什么情况?read()调用将返回 0,表示文件结尾。有点令人惊讶的是,write()函数可以在文件结尾后的任意位置写入数据。

在没有向其中写入数据的时候,文件空洞是不占内存的。但是一旦向其中写入一些数据,则操作系统会为这些数据分配存储空间。但是文件的大小并不会变

所谓的文件空洞就是会占用名义存储空间,但是不会占用实际存储空间。但是对于不支持的文件空洞的文件系统来说,就会直接将数据直接存储到存储空间里。

参考资料

  • 《Linux-Unix系统编程手册》

系统编程-文件系统IO
https://ysc2.github.io/ysc2.github.io/2024/02/27/Linux中的系统编程-文件系统IO/
作者
Ysc
发布于
2024年2月27日
许可协议