3.2Apue文件IO——lseek以及文件共享的概念

当前文件偏移量

每个打开文件都有一个与其相关联的当前文件偏移量
它通常是一个非负的整数,用来度量从文件开始处计算的字节数
读写操作一般都从当前文件偏移量处开始,并使偏移量增加所读写的字节数
特例:除非在打开文件时指定O_APPEND可选项,否则当前文件偏移量默认是0

lseek函数

原型:
在这里插入图片描述
它希望显式地对文件描述符fd相关联的一个打开文件设置偏移量offset
对偏移量offset的解释,与参数whence有关:

  1. whence=SEEK_SET,则将该文件的偏移量设置为距文件开始处offset个字节offset只可为正
  2. whence=SEEK_CUR,则将该文件的偏移量设置为其当前值加上offsetoffset可正可负
  3. whence=SEEK_END,则将该文件的偏移量设置为文件长度加上offsetoffset可正可负

返回值:返回新的文件偏移量

注意:不能对管道,FIFO或网络套接字设置偏移量,否则lseek函数将返回-1

lseek函数使用示例

对于一个hello文件
在这里插入图片描述
① 获得其文件大小
② 设置其文件偏移量为6,则对该文件调用read函数或write函数时,将会从字母l处开始读取/写入。
在这里插入图片描述

/// for read()
#include <unistd.h>

/// for open()
#include <sys/types.h> /// for lseek()
#include <sys/stat.h>
#include <fcntl.h>

/// for printf()
#include <stdio.h>

#define BUFFERSIZE 1024

int main(int argc, char *argv[]) {  
    int fd = open(argv[1], O_RDONLY);
	
	char buf[BUFFERSIZE];
	lseek(fd, 6, SEEK_SET);
	int n = read(fd, buf, BUFFERSIZE);
	buf[n] = '\0';
	write(STDOUT_FILENO, buf, n);
    
	return 0;
}

如果是对文件进行写操作,那么在一次写成功之后,文件偏移量会增加实际写的字节数。


文件共享

内核使用3种数据结构表示打开文件:

  1. 每个进程在进程表中都有一个记录项记录项中包含一张打开文件描述符表。与每个文件描述符相关联的是:a.文件描述符标志b.指向一个文件表项的指针
  2. 内核为所有打开文件维持一张文件表,每个文件表项包含:a.文件状态标志b.当前文件偏移量c.指向该文件v节点表项的指针
  3. 每个打开文件都有一个v节点结构。v节点包含了文件类型对此文件进行各种操作函数的指针

图示为一个进程两个不同的打开文件的内核数据结构
在这里插入图片描述

图示为两个进程各自打开了同一个文件的内核数据结构
可以看到,打开该文件的每个进程都将获得各自的一个文件表项,但对一个给定的文件共享一个v节点表项(v节点包含了文件类型对此文件进行各种操作函数的指针
在这里插入图片描述

聪明的你可能从上图意识到了,当多个进程去写同一个文件时,可能会产生自己没办法预料的结果
这样说:假如open文件时没有使用可选项O_APPEND
① 进程A调用lseek,将文件当前偏移量设置为1500字节。
② 然后内核切换进程,B运行也执行lseek,也将文件当前偏移量设置为1500字节。然后调用write,写入100字节,此时文件长度增加到1600字节。
③ 进程A恢复运行,调用write又写了100字节数据,此时它将从1500字节开始写入,覆盖了B写入了100字节

猜你喜欢

转载自blog.csdn.net/CSDN_dzh/article/details/85057847