栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

第三章-文件I/O

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

第三章-文件I/O

一、相关函数 1.open
#include 
int open(const char* path, int oflag, .../mode_t mode/);
//成功返回文件描述符,失败返回-1

path参数为要打开或创建文件的名字,oflag用下面一个或多个常量“或”运算(只列出常用):

  • O_RDONLY:只读打开
  • O_WRONLY:只写打开
  • O_RDWR:读写打开
  • O_EXEC:只执行打开
  • O_SEARCH:只搜索打开(应用与目录)
    以上五个必须指定一个,且只能指定一个。以下常量是可选的
  • O_APPEND:追加写
  • O_CLOEXEC:把FD_CLOEXEC常量设置成文件描述符标志
  • O_CREAT:若此文件不存在则创建。使用此选项时,同时需要说明第三个参数mode,用该mode指定该文件的访问权限位
  • O_NONBLOCK:非阻塞
  • O_TRUNC:若此文件存在,且为写或读写成功打开,则将其长度截断为0
  • O_SYNC:使每次write等待物理I/O操作完成,包括由该write操作引起的文件属性更新所需的I/O
  • O_DSYNC:使每次write等待物理I/O操作完成,但若该写操作并不影响读取刚写入的数据,则无需等待文件属性被更新
  • O_RSYNC:使每一个以文件描述符作为参数进行的read操作等待,直至所有对文件同一部分挂起的写操作都完成

由open函数返回的描述符一定是最小的未用描述符值。这一点被某些应用程序用来在标准输入、标准输出或标准错误上打开新的文件。

2. creat

创建新文件:

#inlcude 
int creat(const char* path, mode_t mode);
//返回为(只写打开的)文件描述符,若出错返回-1

等同于以下open

open(path, O_WRonLY | O_CREAT | O_TRUNC, mode)
3. close
#include 
int close(int fd);
//成功返回0,失败返回-1

关闭一个文件时会释放该进程加在该文件上的所有记录锁。
当进程终止时,内核自动关闭它所有的打开文件。

4.lseek

每个打开文件都有一个与其相关联的“当前文件偏移量”(current file offset)。通常是非负整数,记录文件从开始处计算的字节数。当打开一个文件时,除非指定O_APPEND选项,否则该偏移量设置为0。
可调用lseek显示地为一个打开文件设置偏移量:

#include 
off_t lseek(int fd, off_t offset, int whence);
//成功时返回新的文件偏移量,失败返回-1

对参数offset的解释与参数whence的值有关。

  • 若whence是SEEK_SET,则将该文件的偏移量设置为距文件开始处offset个字节
  • 若whence是SEEK_CUR,则将该文件的偏移量设置为当前值加offset,offset可正可负
  • 若whence是SEEK_END,则将该文件的偏移量设置为文件长度加offset,offset可正可负

例如可用以下方式确定打开文件的当前偏移量:

off_t curpos;
curpos = lseek(fd, 0, SEEK_CUR);

这种方法也可用来测试所涉及的文件是否可以设置偏移量。若文件描述符指向的是一个管道、FIFO或socket,则lseek返回-1,并将errno设为ESPIPE。
注:对于普通文件,当前的偏移量必须是一个非负整数;但是某些设备也可能允许负的偏移量。因为偏移量可能是负值,所以在比较lseek的返回值时应当谨慎,不要测试它是否小于0,而是是否等于-1。

5. read
#include 
ssize_t read(int fd, void* buf, size_t nbytes);

返回读到的字节数,若已到文件尾,返回0;若出错,返回-1。

6. write
#include 
ssize_t write(int fd, const void* buf, size_t nbytes);

返回值通常与参数nbytes相同

二、I/O的效率 三、文件共享

内核使用3种数据结构表述打开文件,它们之间的关系决定了在文件共享方面,一个进程对另一个进程可能产生的影响。
(1)每个进程在进程表中都有一个记录项,其中包含一张打开文件描述符表,每个描述符占用一项。每一项包括:

  • 文件描述符标志
  • 指向一个文件表项的指针

(2)内核为所有打开文件维护一张文件表。表项包括:

  • 文件状态标志
  • 当前文件偏移量
  • 指向该文件v/i节点表项的指针

(3)每个打开文件都有一个v-node结构。对于大多数文件,v节点还包含了该文件的i节点(i-node, 索引节点)。这些信息都是在打开文件时从磁盘读入内存的。Linux没有使用v节点,而是使用了i-node。但两者概念是一样的,都指向文件系统特有的i-node结构。
注:关于文件系统的i-node,见另一篇博客https://blog.csdn.net/sunximei/article/details/120593787

多个进程读取同一个文件能正确工作。因为每个进程都有它自己的文件表项
,其中也有它自己的当前偏移量。但是当多个进程写同一文件时,则可能出错。

三、原子操作

一般而言,原子操作(atomic operation)指的是由多步组成的一个操作。即要么执行完全部步骤,要么一步也不执行。

四、函数dup和dup2

复制一个现有的描述符:

#inlcude 
int dup(int fd);
int dup2(int fd, int fd2);

成功返回新的文件描述符,失败返回-1。

  • dup:返回的新文件描述符一定是当前当用描述符的最小值。
  • dup2:可以用fd2参数指定新描述符的值。如果fd2已经打开,则先将其关闭;若fd等于fd2,则dup2直接返回fd2,否则fd2的FD_CLOEXEC文件描述符标志就被清除,这样fd2在进程调用exec时是打开状态。
    关于FD_CLOEXEC的解释:https://blog.csdn.net/bemf168/article/details/80025365

五、函数sync、fsync、fdatasync

传统的UNIX系统在内核中设有缓冲区高速缓存或页高速缓存,大多数磁盘I/O都通过缓冲区进行。当我们向文件写数据时,内核通常先将数据复制到缓冲区中,然后排入队列,晚些时候再写入磁盘(也叫做delayed write)。

有时需要立马冲洗缓冲区,以下三个函数

#include 
void sync(void);
int fsync(int fd);
int fdatasync(int fd);

成功返回0,失败返回-1(除了sync)

  • sync:只是将所有修改过的块缓冲区排入写队列,然后就返回,并不实际等待写磁盘操作结束。通常,update系统守护进程周期性地(一般30s一次)调用sync函数。保证定期冲洗(flush)内核缓冲区。
  • fsync:只对fd指定的一个文件起作用,并且等待写磁盘操作结束才返回。
  • fdatasync:类似于fsync,但只影响文件数据部分;而fsync还会同步更新文件的属性
六、函数fcntl

改变已经打开文件的属性:

#include 
int fcntl(int fd, int cmd, ...);

在本节中,第三个参数只是整数。
失败返回-1,成功时,返回值依赖cmd
fcntl函数有以下5种功能:
(1)复制一个已有的描述符(cmd = F_DUPFD或F_DUPFD_CLOEXEC)
(2)获取/设置文件描述符标志(cmd = F_GETFD或F_SETFD)
(3)获取/设置文件状态标志(cmd = F_GETFL或F_SETFL)
(4)获取/设置异步I/O所有权(cmd = F_GETOWN或F_SETOWN)
(5)获取/设置记录锁(cmd = F_GETLK、F_SETLK或F_SETLKW)

七、函数ioctl 八、/dev/fd
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/300030.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号