一、文件操作I/O
1 | fd = open(pathname,flags,mode) | 打开文件返回文件描述符 | flag指定打开方式及一些限制,mode指定文件访问权限 |
2 | numread = read(fd,buffer,maxszie) | 读文件 | 自动更新文件偏移量 |
3 | numwrite = write(fd,buffer,maxszie) | 写文件 | 自动更新文件偏移量 |
4 | status = close(fd) | 关闭文件 | 释放文件描述符资源 |
5 | offset_cur = lseek(fd,offset,whence) | 改变文件偏移量 | SEEK_SET、SEEK_CUR、SEEK_END |
6 | ioctl(fd,request,…) | ioctl系统调用来控制设备 | |
7 | flags = fcntl(fd,cmd,…) | 1.读取和设置打开文件的状态标记flags 2.F_DUPFD复制文件描述符 | F_GETFL和F_SETFL分别是检索和修改flags标志位的,能够更改的标志位有限制 |
8 | new_fd = dup(old_fd) | 复制文件描述符 | 这两个描述符共享相同的内部结构,共享所有的锁定,读写位置和各项权限或flags等等 |
9 | res = dup(old_fd,new_fd) | 复制文件描述符,且指定新的文件描述符 | 如果由new_fd指定的文件描述符之前已经打开,那么dup2回将其关闭。关闭old_fd时dup2回忽略关闭出现的任何异常,更为安全的做法是在dup2之前检查new_fd是否打开,若打开,就close关闭。 |
10 | pwrite(fd,buf,count,offset) | 与write类似,只在offset处进行I/O操作 | pread和pwrite不会改变当前文件的偏移量。 |
11 | pread(fd,buf,count,offset) | 与read类似 | 只在offset处进行I/O操作 |
12 | readv(fd,iovec *iov,cnt) preadv(fd,iovec *iov,cnt,offset) | 分散输入 | |
13 | writev(fd,iovec *iov,cnt) pwritev(fd,iovec *iov,cnt,offset) | 集中输出 这些系统调用一次性即可传输多个缓冲区的数据,原子操作 | |
14 | truncate、ftruncate | 截断文件 | |
15 | fd = mkstemp(path) File* tmpfile() | 生成临时文件 | 有些程序需要创建一些临时文件,仅供程序在运行期间使用,程序终止后就删除。 |
二、open flags介绍
三、文件空洞
lseek()系统调用可以改变文件的偏移量,但如果程序调用使得文件偏移量跨越了文件结尾,然后再执行I/O操作,将会发生什么情况? read()调用将会返回0,表示文件结尾。令人惊讶的是,write()函数可以在文件结尾后的任意位置写入数据。在这种情况下,对该文件的下一次写将延长该文件,并在文件中构成一个空洞,这一点是允许的。从原来的文件结尾到新写入数据间的这段空间被成为文件空洞。调用write后文件结尾的位置已经发生变化。
文件空洞占用任何磁盘空间,直到后续某个时点,在文件空洞中写入了数据,文件系统才会为之分配磁盘块。空洞的存在意味着一个文件名义上的大小可能要比其占用的磁盘存储总量要大(有时大出许多)。向文件空洞中写入字节,内核需要为其分配存储单元,即使文件大小不变,系统的可用磁盘空间也将减少
四、系统调用的原子性
所有系统调用都是以原子操作方式执行的,内核保证了某系统调用中所有步骤作为独立操作而一次性执行完毕,中间不会被其它线程、进程所中断。
总之注意一点:单个系统调用可以确保原子性,但是两个系统调用之间就不能确定原子性,O_CREAT和O_EXCL一次性地调用open()可以确保检查文件和创建文件的步骤属于一个单一的原子(不可中断的)操作。
五、文件描述符与打开文件
-
进程级的文件描述符表
• 控制文集描述符操作的一组标志
• 对打开文件句柄的引用 -
系统级的打开文件表:表中条目称之为打开文件句柄,文件句柄中存储了与一个打开文件相关的全部信息
• 进程对文件的读写偏移量
• 打开文件时所用的状态标志
• 文件访问模式
• 与信号驱动I/O有关的设置
• 对该文件i-node对应的引用 -
文件系统索引节点表:i-node表存储文件的元信息
• 文件字节数
• 文件拥有者User ID、Group ID
• 文件rwx权限
• 文件的3个时间戳:ctime(inode上一次变动时间)、mtime(文件内容上一次变动时间)、atime(文件上一次打开时间)
• 链接数
• 文件数据block位置
可以使用stat命令查看某个文件的 inode信息
总结:
- 两个不同的文件描述符,若指向同一打开的文件句柄,将共享同一文件偏移量。如果通过其中之一的fd修改文件偏移量,那么另外一个文件描述符也会察觉这个辩护
- 文件描述符标志位进程和文件描述符私有。