Linux环境编程之文件I/O(四):文件I/O的数据结构
来源:互联网 发布:mac windows10 iso 编辑:程序博客网 时间:2024/05/16 14:43
(一)
Linux系统支持不同进程间共享打开的文件。内核使用三种数据结构表示打开的文件:进程表项、文件表项、v节点表。
1、进程表项:每个进程在进程表中都有一个记录项,记录项中年包含有一张打开文件描述符表,可将其视为一个矢量,每个描述符占用一项。与每个文件描述符相关联的是:
a、文件描述符标志
b、指向一个文件表项的指针
2、内核为所有打开文件维持一张文件表。每个文件表项包含:
a、文件状态标志,如读写、添加、同步和非阻塞等。
b、当前文件偏移量
c、指向该文件v节点表项的指针
3、每个打开的文件都有一个v节点结构。v节点包含了文件类型和对此文件进行各种操作的函数的指针。对于大多数文件,v节点还包含了该文件的i节点。
如果两个独立进程各自打开了同一个文件,假定第一个进程在文件描述符3上打开该文件,而另一个进程则在文件描述符4上打开该文件。打开该文件的每个进程都得到一个文件表项,但对一个给定的文件只有一个v节点表项。每个进程都有自己的文件表项的理由是:这样使得每个进程都有它自己的对该文件的当前偏移量。如下图:
注意三个概念:文件描述符标志、文件状态标志、文件描述符。
文件描述符标志(close_on_exec),它仅仅是一个标志,当fork了一个子进程,然后在子进程中调用了exec函数时就用到了该标志,它的含义就是,执行exec钱是否要关闭这个文件描述符,它的作用域只用于一个进程的一个描述符。而文件状态标志是在系统文件表中,读写可执行等这些标志,适用于指向该给定文件表项的任何进程中的所有描述符。
(二)
既然文件可以共享,那不同进程间共享同一个文件时,就可能出现并发竞态等问题。针对不同的竞态问题,我们有不同的策略。
1、若两个进程同时对一个文件进行写操作,则可能使其中一个的写数据被另外一个的写数据覆盖,针对这种情况,采取的办法是在open打开文件时设置O_APPEND标志。
2、Linux还允许原子性地定位搜索(seek)和执行I/O。其中pread和pwrite就是这种的函数。
#include <unistd.h>
ssize_t pread(int fd, void *buf, size_t count, off_t offset);
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
调用pread相当于顺序调用lseek和read,但pread又与这种顺序调用有下列区别:
a、调用pread时,无法中断其定位和读操作。
b、不更改文件指针
调用pwrite相当于顺序调用lseek和write,但也与他们有类似的区别。
(三)
可以使用dup和dup2函数复制一个现存的文件描述符
#include <unistd.h>
int dup(int oldfd); // 返回的新文件描述符一定是当前可用文件描述符中的最小数值。
int dup2(int oldfd, int newfd); // 可以用newfd参数指定新描述符的数值,如果newfd已经打开,则现先将其关闭。如果newfd等于oldfd,则dup2返回newfd,而不关闭它。
#include <stdio.h>#include <unistd.h>#include <sys/stat.h>#include <fcntl.h>intmain(int argc, char *argv[]){int fd;int nfd;char buf[] = "fjakdjl";fd = open("test.txt", O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);if(fd < 0)printf("open error\n");printf("fd = %d.\n", fd);//dup2nfd = dup2(fd,4);if(nfd < 0){printf("error!\n");}printf("nfd = %d.\n", nfd);return 0;}编译测试:
编译gcc dup.c执行./a.out显示结果fd = 3.nfd = 4.
(四)
为保证磁盘上实际文件系统与缓冲区高速缓存中内容的一致性。Linux系统提供了sync、fsync、fdatasync三个函数。
#include <unistd.h>
int fsync(int fd); //只对文件描述符fd指定的单一文件起作用,并且等待写磁盘操作结束,然后返回
int fdatasync(int fd); // 类似于fsync,但它只影响文件的数据部分,出数据部分外,fsync还会同步更新文件的属性。
void sync(void); // 只是对所有修改过的快缓冲区排入写队列,然后就返回,它并不等待实际写磁盘操作。
- Linux环境编程之文件I/O(四):文件I/O的数据结构
- Linux环境编程之文件I/O(八):文件链接
- Linux环境编程之文件I/O(五):fcntl函数
- Linux环境编程之文件I/O(六):文件属性
- linux系统编程之文件I/O
- linux 文件I/O 编程
- Linux 文件I/O编程
- linux文件I/O编程
- linux文件I/O编程
- linux系统编程之文件与I/O(四):文件的属性
- linux系统编程之文件与I/O(四):文件的属性
- linux系统编程之文件与I/O(四):文件的属性
- Linux的文件I/O编程
- Linux环境编程之文件I/O(二):文件的打开与关闭
- Linux环境编程之文件I/O(三):文件的读写
- Linux环境编程之文件I/O(二):文件的打开与关闭
- UNIX环境编程学习笔记(3)——文件I/O之内核 I/O 数据结构
- Linux的那些事儿(5)----Linux环境下编程之文件I/O
- 昨天是母亲节,祝母亲天天开心,永远健康
- 2-05. 求集合数据的均方差(15)
- fedora(cent os) +Apache+PHP+MySQL服务器环境
- 走在最前端的转换软件
- Oracle的For Update语句
- Linux环境编程之文件I/O(四):文件I/O的数据结构
- POJ 1149 PIGS 网络流Dinic
- VLC播放器插件检测
- vim 折叠 与 打开头文件
- TC-SRM618div1-500
- sqlite
- Android Tween动画之RotateAnimation实现图片不停旋转
- spring源码解析_BeanFactory
- 当时还罗列过很多不挣钱原因以及建议