首页 » 网站建设 » phparrayfilp技巧_文件IO文件描述符与lseek

phparrayfilp技巧_文件IO文件描述符与lseek

访客 2024-11-18 0

扫一扫用手机浏览

文章目录 [+]

可以设想,在一个进程中,存在着一个大数组(记录了打开的文件),这个数组的索引号便是 open 函数返回的整数,而这个数组的每一项,记录了打开的文件干系信息。

我们知道,在操作系统中,是通过进程掌握块(PCB)来描述进程信息和干系资源的。
实际上在 linux 中,它便是一个巨大的构造体,在 linux 0.11 中,便是 task_struct 构造体。
为了便于学习,我把其它用不着的部分先删除了。
(代码来源于 linux 0.11,由于我们是初学者,学习这个版本的源码足够了。

phparrayfilp技巧_文件IO文件描述符与lseek

从下面的PCB构造体中,确实存在着这么一个数组 filp[NR_OPEN]。

phparrayfilp技巧_文件IO文件描述符与lseek
(图片来自网络侵删)

struct task_struct { long pid; // 进程号 // ... 其它字段 // 文件描述符标志位,有关该标志位,往后再说。
unsigned long close_on_exec; // 数组索引号便是文件描述符。
NR_OPEN 的值在 linux 0.11 中被定义为 20 struct file filp[NR_OPEN]; // ... 其它字段};1234567891011

那么 struct file 长啥样呢?我们知道它记录了文件的干系信息,还记得open函数的几个参数吗?有 flag, 它记录了文件状态,比如O_RDONLY,O_WRONLY,O_APPEND等等?有 mode,文件的权限位。
可以预测,这个struct file 也记录着这些属性。
下面是 linux 0.11 源码中的数据构造。

struct file { unsigned short f_mode; // 文件权限位 unsigned short f_flags; // 文件状态位 unsigned short f_count; // 引用计数 struct m_inode f_inode; // 文件存在磁盘上的哪个位置等等其它信息由这个字段来阐明 off_t f_pos; // 当前偏移量};1234567

用下面这张图来描述 PCB,文件描述符,文件表之间的关系,会更加清晰。

图1 PCB,文件描述符与文件表

上图中的 flip 数组的索引号,便是文件描述符。
数组中的每个元素是一个指向了 struct file 类型(文件表)的指针,struct file(文件表)中记录了当前打开的文件的主要信息,个中根据 f_inode 成员就可以找到磁盘上的文件(实际由 f_inode 到磁盘文件没有图中那样大略,要稍稍繁芜点,不过为相识释问题,大家暂时可以这样理解,后面到文件系统的时候会深入)。
相信到这里,你已经理清了描述符,文件表之间的关系了。
在上图中,可以看到本进程中有三个文件描述符指向了同一个文件表,那么这个文件表中的引用计数一定为 3。
用 C 措辞来讲便是 flip[0] == flip[1] && flip[1] == flip[2]。
而第二个文件表只有一个指针指向了它,它的引用计数便是1.在调用 close(fd) 函数的时候,实际上做了两步:

--flip[fd]->count; flip[fd] = NULL;12

当 count == 0 的时候,才真正的关闭文件。

有没有可能人为的让两个不同的描述符指向同一个文件表?答案是完备可能,这没什么好奇怪的,函数 dup 和 dup2 便是干这事的。
dup2(int oldfd, int newfd) 的函数做的事情大概就向下面这个样子:

int dup2(int oldfd, int newfd) { // ... close(newfd); flip[newfd] = flip[oldfd]; flip[newfd]->count++; //... return 0;}12345678

而 dup 函数只接管一个参数 oldfd,它返回系统分配的新描述符值。

并非所有的操作系统实现办法都如图 1 中所示,在 linux 0.11 中采取的是数组,当然,完备可以采取链表来实现,这取决于不同操作系统的实现办法,万变不离其宗。

2. lseek 函数函数原型

// off_t 可以理解成 intoff_t lseek(int fd, off_t offset, int whence);12

lseek 函数,便是改变 flip[fd] 指向的 struct file 这个构造中的 f_pos 成员的。

当用 open 函数打开一个文件的时候,该偏移量 f_pos 被默认指定为 0。

如果 whence 即是 SEEK_SET,则 f_pos = offset(offset 只能是正数)如果 whence 即是 SEEK_CUR, 则 f_pos = f_pos + offset(offset 可正可负)如果 whence 即是 SEEK_whence,则 f_pos = 文件长度 + offset (offset 可正可负)3. 指定 f_pos 后有什么影响?

如果一个文件中的内容是 hello world,当f_pos==6的时候,实行 read 函数将从字母w开始读取,实行write 也会从 w处开始写数据。

4. 示例目录树

.|-lseekdemo.c|-test123test 文件

hello world1lseekdemo.c

#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>int main() { int fd = open(\"大众test\公众, O_RDONLY); if (fd < 0) { perror(\"大众open\公众); return 1; } char buf[64] = {0}; lseek(fd, 6, SEEK_SET); read(fd, buf, 64); printf(\公众%s\n\"大众, buf); return 0;}123456789101112131415161718

编译后实行,屏幕会打印 world.

5. 总结理解文件描述符是什么知道 struct file 构造体理解 lseek 事理节制 lseek 用法
标签:

相关文章

微信第三方登录便捷与安全的完美融合

社交平台已成为人们日常生活中不可或缺的一部分。微信作为我国最受欢迎的社交软件之一,拥有庞大的用户群体。为了方便用户在不同平台间切换...

网站建设 2025-02-18 阅读1 评论0

广东高速代码表解码高速公路管理智慧

高速公路作为国家交通动脉,连接着城市与城市,承载着巨大的物流和人流。广东作为我国经济大省,高速公路网络密布,交通流量巨大。为了更好...

网站建设 2025-02-18 阅读1 评论0