17,UC(06)
/*
达内学习 UC day06 2013-10-10
*/
回忆过去:
系统调用 - UNIX操作系统提供的一些列函数皆苦,用于访问内核空间,遵循posix规范
文件操作:open()\read()\write()\close() 函数的使用
lseek() - 移动文件内指针,设置偏移量
dup()/dup2() - 文件描述符的复制
fcntl() - 文件控制函数,提供很多功能 文件相关函数
lseek() 用法和fseek() 基本一致,第一个参数是文件描述符,第二个参数是偏移量,第三个参数是偏移的参照位置,包括SEEK_SET(头)SEEK_CUR(当前) SEEK_END(文件结尾)
dup()和dup2()都可以复制文件描述符,但是不会复制文件表
dup() 复制描述符时候,新的描述符由系统选定
dup2()复制时,描述符由程序传入,如果改值被占用,关闭后使用传入的值
int fcntl(int fd,int cmd,...)
通过不同的cmd 执行不同的操作,常见的cmd
1 F_DUPFD 复制文件描述符 需要第三个参数传入新描述符的值,但返回描述符的值大于等于传入的值的最小值(不像dup2强制关闭)
2 F_GETF 取文件的权限和状态,取不到创建标记,不需要第三个参数
3 F_SETFL 设置文件的状态标记,支队O_APPEND 有效
4 文件锁的操作和使用。
当多个进程同时访问同一个文件时,有可能引发数据访问错误,因此为了保证数据有效,需要用文件锁 控制多个进程对同一个文件读写操作p。
文件锁:在一个进程操作文件时,锁定其他进程对文件的操作,直到结束对文件的操作。
目前文件锁都采用读写锁,分为读锁和写锁
读锁:共享锁,允许多个进程对文件的某个区域加读锁
写锁:互斥锁,排他锁,只能有一个进程加锁。
加了读锁的区域,不能再加写锁
结论:如果一个进程对文件的某个区域加了读锁,其它进程可以对该区域加读锁,但不能加写锁,如果一个进程对文件的某个区域加了写锁,其他进程对该区域不能加任何锁
文件锁锁定文件的某部分
fcntl()对文件加锁解锁 int fcntl(int fd, int cmd, ... /* arg */ );
cmd可以是
F_SETLK 加锁/解锁 如果加不上锁,返回-1 F_SETLK (struct flock *)
F_SETLKW 加锁/解锁,如果加不上锁 等待 出错返回-1
F_GETLK 测试某个锁能某加上,但不真正加锁
文件锁用 struct flock 代表
struct flock
{
short l_type; //锁的类型 F_RDLCK F_WRLCK,F_UNLCK
short l_whence;//锁的起始点参照
int l_start; //锁的起始点的偏移量
int l_len; //锁的长度
pid_t l_pid;F_GETLK专用,SET时不用,-1即可
}
锁定起始点 由l_where 和 l_start联合决定
注:1 加读锁/写锁fd要有对应权限
2 进程结束会释放锁,但程序员应该读写完毕就主动释放锁,fcnl(fd,F_SETLK,&lock)其中lock的l_type设置为F_UNLCK即可
文件锁起始不是对read()/write()等读写函数的锁定,而是阻止其他进程对文件的莫个区域进行加锁,文件锁正确的使用方法是:
在调用read()之前加读锁,调用write()之前加写锁
F_GETLK测试一个锁能否被加上,如果能加上,会把锁的类型改成G_UNLCK,其他不变,不能加会把锁的成员改成当前正在锁定的那个锁(不能锁的原因),并且把l_pid改成加锁的进程,一般用pid是否等于-1判断是否能加锁。
C语言描述时间的方式
time_t -秒差(和1970年1月1日0点0分0秒的秒差)
struct tm - 结构体 成员包括 年,月,日,小时,分,秒
内存地址表示变量在内存中的位置,i节点表示文件/目录在硬盘中的位置
文件表中存储的数据:1 文件偏移量;2 文件描述符的状态(内存中);3 文件自身的属性(硬盘中文件信息)