open close write read lseek 调整文件的读写位置
1.1 标C文件处理和UC文件处理函数的比较
根据程序的结构可知,标C的文件处理函数比UC的文件处理函数速度快,因为标C函数内部都有输入输出缓冲区,会积累一定数量之后再写入文件,因此读写的效率比较高,使用 time 命令来查看程序运行的时间。
real 真实时间 user 用户态时间 sys 内核态时间;
注意
对于UC的文件处理函数来讲,可以通过自定义缓冲区来提高读写的效率。
1.2 文件描述符
i节点编号,是硬盘文件位置的唯一标识。i节点之前V节点主要包含V节点信息,i节点信息,用来维护i节点的信息,v节点之前存在文件表,主要是文件的标识信息,第二部分是文件的读写位置,第三部分是v节点指针。进程中包括文件描述符,文件表指针,文件描述符用来对应文件表指针,
文件描述符就是一个整数,可以代表一个打开的文件,但是文件的信息不是存在一个文件描述符之中,而是在文件表等结构中,当打开一个文件时候,系统会把文件信息存入文件表等结构中,但是出于安全考虑,文件表等结构不能直接操作,而是给文件表对应一个编号,我们用编号进行操作,标号就是文件描述符。
在进程内部,维护着一张文件描述符的总表,当使用open 函数打开文件时候,就会加载该文件的信息到内存中,然后去文件描述符的总表中查找一个最小的未被使用的描述符建立和文件表的对应关系,而文件描述符是一个非负整数,从0开始一直到 OPEN_MAX在linux 中一般书255 ,其中012 被系统占用,分别代表标准输入,标准输出个标准错误,
close 函数的工作方式: 表示先把对应关系从文件描述符总表中删除,不一定会删除文件表,只有当文件表不会和任何其他文件描述符有对应关系时候(也就是文件表可以对应多个文件描述符),才会删除文件表,也就是说close函数不会改变文件描述符的整数值,只是会让该描述符无法代表一个文件
在同一个进程或者不同的进程,多次打开同一个文件的时候,文件表会产生多个,但是v节点只有一个。
1.3 dup/dup2/函数
#icnlude
int dup(int oldfd);
函数功能
根据参数指定的文件描述符进行复制,成功返回新的文件描述符,失败返回-1;
使用完这个函数之后,要使用close 进行关闭文件。使用这个函数之后生成的文件描述符和原来的文件描述符所对应的是同一个文件表。
int dup(int oldfd,int newfd);
主要用于将 oldfd 参数指定的文件表地址拷贝到newfd中,如果newfd 被占用则关闭,成功返回新的文件描述符,失败返回-1;
注意 :
dup/dup2函数用于赋值文件描述符时候,实质上是文件描述符所对应的文件表地址,也就是让多个文件描述符对应同一个表,从而对应同一个文件。
1.4 fcntl 函数 (重点 复杂)
#include
#include
int fcntl(int fd,int cmd,...);
fd 文件描述符
cmd 命令操作 执行什么操作,函数的主要作用就是根据cmd 进行操作,
1 F_DUPFD 复制文件描述符,新的文件描述符会选择大于等于arg 的值作为参数fd 的备份。不会强制关闭正在使用的描述符。
2 F_GETFD/F_SETFD - 获取和设置文件描述符标志
3 F_GETFL/F_SETFL 获取和设置文件的状态标注
4 F_GETLK/F_SETLK/F_SETLKW 增加释放和判断锁是否存在。
可变长参数 是否需要取决于第二个
返回值
F_DUPFD 成功返回新的文件描述符,失败返回-1;
F_GETFD/SETFD 成功返回获取标志 0 失败返回-1;
F_GETFL/F_SETFL 成功返回0,失败返回-1;
F_SET/F_SETLKW/F_GETLK 成功返回0;失败返回-1;
函数功能:
1 主要是用来复制文件描述符
2 设置/获取文件描述符的功能
3 设置获取文件状态标志的功能
4 实现建议型文件锁的功能(要求掌握)
1.5 使用fcntl实现文件锁的功能
1 文件锁的作用
当有多个进程同时对一个共享文件进行读写操作时候,可能对数据造成混乱和不一致性,理论上要求多个进程对文件操作进行串行不是并行。如果两个进程都是读取文件则允许同同时进行,只要有一个写操作,另外一个进程应该等待,为了实现这个功能,需要借助文件锁。
文件锁就是读写锁,也就是一把读锁和一锁把写锁,其中读是一把共享锁,不允许其他进程加写锁。可以加读锁,而写锁是一把互斥锁,不允许其他进程加读锁和写锁。
2 实现文件锁的功能,fcntl函数的cmd 参数F_SETLK/F_SETLKW/F_GETLK
第三个参数的取值
是一个指向一下结构体类型的指针。结构体是
struct flock
{
short l_type; 锁的类型 读锁写锁解锁
short l_whence;起始位置
off_t l_start; 偏移的字节
off_t l_len; 枷锁的字节数
pid_t l_pid; 加锁的进程号
}
3 F_SETLK 主要用于加锁或者解锁