首先要知道LINUX中一切都是文件,文件有好多种类型,一般有普通文件,目录文件,连接文件。一个文件一般有9个权限,分别是所有者的权限,群组权限,其他人的权限。
文件还有一些时间参数:access time, modification time , change-status time。
access time指的是文件的最近读取时间。
modification time指的是文件内容的最近修改时间。
change-status time值的是文件权限的最近修改时间。
文件的类型与权限属性一般在mode_t这个类型里面。可以用
S_ISXXX宏来判断一个文件的类型,这个宏的参数是mode_t类型。
int open(const char *path, int oflag, ... /*mode_t mode */)
path:指文件的位置
oflag:有很多,一般有5个是互斥的
下面再说以其他比较重要的参数:
注意点:
open返回的是当前可以使用的最小的文件描述符。
int creat(const char *path, mode_t mode);
/*
这个函数返回的是一个write-only的文件描述符,出错返回-1。
mode表示的是文件的那9个权限
*/
用途:用于定位一个打开的文件
off_t lseek(int fd, off_t offset, int whence)
/*
whence:
SEEK_SET:从头开始+offset
SEEK_CUR:从当前位置+offset
SEEK_END:从文件结束位置+offset
返回的是新的offset;失败返回-1
*/
注意点
sszie_t write(int fd, const void *buf, size_t nbytes);
/* 返回的是你写入的数量 */
注意点:
1.write一个文件时,文件表中的file offset会移动。如果write一个文件时,他的offset超过了文件的大小,那么就会设置该文件inode中的大小为当前offset大小。
2.如果文件的flag是O_APPEND,那么每次写的时候文件表中的offset都会设置为inode中的文件大小。
3.如果我们是从lseek获取文件的末尾时,也会从inode获取文件大小,并且设置文件表中的对应值。但是如果是多线程时,lseek之后发生进程切换,并且另一个进程也写到这个文件,就会发生第一个进程写的时候写的不是文件末尾。
例子:
if(lseek(fd, 0, SEEK_END) < 0)
err_sys("lseek error");
if(write(fd, buf, 100) != 100)
err_sys("write error");
上面的这个程序,如果在多线程环境中,可能会出现bug,如果有A执行了lseek,定位到了文件末尾。然后进程调度,现在轮到B执行且写入到了这个文件中,这时再由A执行时,A对于这个文件的偏移就不是文件末尾了。这一点一定要理解。
int fsync(int fd); /* 成功返回0, 失败返回-1 */
void sync(void);
kernel会维护一个buffer,把一些数据保存在这个buffer中。kernel会把所有延迟写的数据块在buffer已经要回收时写到硬盘中。
注意点:
sync 只是下达命令表示所有在排队的写数据要写到磁盘了,然后就返回,再由内核负责把数据写到磁盘,但是后面这个过程sync就不知道了。
fsync,就不一样了,他表示的是我要等到我这个文件写到磁盘,我再返回。通过fsync,文件的属性也会同时被更新
说明:
fcntl函数可以改变一个打开文件的属性
注意要设置文件的属性时,若果想要有以前的属性,那么要先获得,然后再去设置,因为设置是把文件一下都设为那个属性
int fcntl(int fd, int cmd, .../* int arg */);
/* 返回值依赖于cmd */
cmd的取值即说明:
1.F_DUPFD与F_DUPFD_CLOEXEC
F_DUPFD会把新的文件描述符中的flags字段的FD_CLOEXEC属性清掉,而F_DUPFD_CLOEXEC不会
2.F_GETFD, F_SETFD
用来获取以及设置文件描述符的flags
F_GETFD与F_SEETFD都是与file descriptor flags有关,注意区分
3.F_GETFL, F_SETFL
F_GETFL与F_SETFL都是与file status flags有关
上面5个属性是互斥的,即是说有且只能有一个,所以测试时要先使用O_ACCMODE与val(我们获得的file status flag)&一下.
如图:
1.先找到一个可用的inode,并得到他的编号:inode number
2.然后给文件分配block
3.在inode的磁盘分区表中填入我们分配的block
4.将”inode number, 文件名”填入目录文件的block中。
注意:
inode是识别文件的唯一标识,所有的文件最终都是通过inode 来识别的。
一个磁盘可以被划分成不同的区域,每个不同的区域可以看成是一个独立的磁盘。
磁盘的上的每个磁道可以划分成扇区,这个扇区就是一个块,它是一个基本的磁盘存储单元,一般大小为512B。我们可以给这些扇区编号,形成块序列
这三个区域为:
super block, 磁盘属性(比如inode table ,block table), data(数据区)
所谓连接就是文件打开表的属性。
其中重要的有O_SYNC,O_APPEND。
注意:
O_CREAT与O_EXCL组合可以消除一个竞争:
如果两个进程同时创建相同的文件,一般操作是先用stat查看文件是否存在,然后调用creat。O_EXCL与O_CREAT组合可以让这两个操作变成一个原子操作。