1.文件共享
UNIX系统支持在不同进程间共享打开文件。先说明这种结构.
每一个进程在进程表中都有一个文件描述符fd。每一个打开的文件描述符都有一个属于自己:
文件状态标志(打开方式,只读只写或者读写)
当前的文件偏移量(文件指针指向的位置)
v节点指针(指向文件信息)
以上这三种是每一个文件描述符自己拥有的,也就是说不能通过别的方式更改。
用两个文件描述符打开同一个文件,那么每一个文件描述符仍然有属于自己的文件状态标志,当前文件偏移量,但是v节点指针指向同一个,因为这是一个文件。
注释:例如更改第一个文件描述符的文件偏移量,第二个文件描述符对应的偏移量不会更改。另外文件状态标志也一样。都是独立的。
2.原子操作
原子操作就是一串连贯的操作。比如说有两个文件描述符A,B指向同一个文件C。想要往C中添加一句HelloWorld。让A添加Hello让B添加World。那么如果咱们电脑非常卡,执行完了A的添加语句可是Hello还没有添加完成,可是执行不卡,那么就开始执行B的添加语句,那么HelloWorld就不一定添加成什么样子了。那么原子操作就是拯救世界的一个东西了==。比如说A的添加语句是一个原子操作,那么A的添加语句是会被挂起,直到添加完成,不会被打扰。原子操作就是吧一个动作连贯的完成而不被打扰。
3.函数pread和pwrite
调用pread相当于调用lseek之后调用read,但是pread又与这种顺序调用有下列重要区别
一、调用pread时,无法中断其定位和读操作
二、不更新当前文件偏移量
pwrite和他相同
4.函数dup和dup2
这两个函数都可以用来复制一个现有的文件描述符。
#include <unistd.h>
int dup(int fd);
int dup2(int fd, int fd2); //fd2是指定的新的描述符
由dup返回的文件描述符一定是当前位被占用的最小数字,dup2是可以指定文件描述符用什么数字的。先进吧==。
如果指定的fd2已经被打开,那么先关闭fd2之后在用这个打开此文件。如果fd2== fd那么就直接返回自己。
注意:这些函数返回的新文件描述符与参数fd共享同一个文件表项
5.函数sync、fsync和fdatasync
传统的unix系统实现在内核中设有缓冲区告诉缓存或者页告诉缓存。大多数磁盘I/O都是通过缓冲区进行。当我们向文件写入数据时,内核通常先将数据复制到缓冲区中。然后排入队列,晚些时候再写入磁盘,这种方式被成为延迟写。
通常,当内核需要重用缓冲区来存放其他磁盘块数据的时候,它会把所有延迟写的数据块写入磁盘。为了保证瓷盘上世纪文件系统与缓冲区的内容一致性,UNIX系统提供了这三个函数。(此为书上原话,无需解释)
#include<unistd.h>
int fsyne(int fd);
int fdatasync(int fd);
void sync(void);
sync只是将所有修改过的块缓冲区排入写队列,然后就返回。它并不等待实际写磁盘操作结束。通常,成为update的系统守护进程周期性的调用(一般每隔30秒)sync函数。这就保证了定期冲洗(flush)内核的块缓冲区。命令sync(1)页调用sync
fsync函数只对有文件描述符fd指定的一个文件其作用,并且等待写磁盘结束才返回。fsync可用于数据库这样的应用程序,这种应用程序需要确保修改过的块立即写到磁盘上。
fdatasync函数类似于fsync,但它之影响文件的数据部分。而除数据外,fsync还会同步更新文件的属性。
6.函数fcntl
fcntl函数可以改变已经打开的文件的属性
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /*int arg */);
函数的返回第一个参数是文件描述符,第二个参数是要更改的东西,第三个参数或者以后的参数根据第二个参数的要求而变化。
详细变化看书81页
7.函数ioctl
终端I/O一直是ioctl使用最多的地方。本章不做过多介绍。了解即可。
8.dev/fd
较新的系统支持/dev/fd的目录。打开文件/dev/fd/n等效于复制描述符n(假定描述符n是打开的)例如
fd= open(“/dev/fd/0”, mode);等效于fd= dup(0);
也就是说通过dev复制的文件描述符和原文件描述符共享同一个文件表项。