《Unix环境高级编程》学习笔记——高级IO

本文详细介绍了Unix环境高级编程中的非阻塞IO、记录锁、IO多路转接(select、poll、epoll)的概念、实现及应用实例。非阻塞IO通过轮询避免阻塞,适用于并发量较小的场景。记录锁用于解决并发文件编辑冲突,确保数据一致性。IO多路转接允许高效处理多个描述符,epoll以其高性能成为优选。
摘要由CSDN通过智能技术生成

一、引言

高级IO包含很多内容,如非阻塞IO、记录锁、IO多路转接(select和poll函数)、异步IO、readv和writev函数以及存储映射IO(mmap)等。

二、非阻塞IO

非阻塞IO使我们可以发出open、read和write这样的I/O操作,并使这些操作不会永远阻塞。

它的特点是:

  1. 进程轮询(重复)调用,消耗CPU资源。(阻塞式IO被阻塞时会挂起,不会消耗CPU资源)
  2. 实现难度低,开发应用相对阻塞IO模式较难。
  3. 适用并发量较小,且不需要及时响应的网络应用开发。

对于一个给定的文件描述符,有两种为其指定非阻塞IO的方法:

  1. 如果调用open获得描述符,则可指定O_NONBLOCK标志。
  2. 对于已经打开的一个描述符,则可调用fcntl,由该函数打开O_NONBLOCK文件状态标志。

非阻塞IO模型:

image

三、记录锁

在大多Unix系统中,当两个人同时编辑一个文件时,该文件最后的状态取决于写该文件的最后一个进程。但大多数时候我们并不希望看到这样的结果,例如在数据库中。为了解决这个问题,Unix提供提供了记录锁机制。

记录锁(record locking)的功能是:当一个进程正在读或修改文件的某个部分时,使用记录锁可以阻止其他进程修改同一文件区。记录锁也可以理解为字节范围锁,因为它锁定的只是文件中的一个区域。

3.1 记录锁的实现

POSIX.1使用fcntl函数来进行记录锁相关操作,其函数原型为:

#include<fcntl.h>
int fcntl(int fd, int cmd, .../* struct flock *flockptr */);
//若成功,依赖于cmd,否则,返回-1

可选参数flockptr是一个flock结构的指针,其结构如下:

struct flock{
    //锁类型 可选值是: 共享读锁:F_RDLCK 独占写锁:F_WRLCK 解锁一个区域F_UNLCK
    short l_type;
    //起始位置 文件头:SEEK_SET 当前位置:SEEK_CUR 文件尾:SEEK_END
    short l_whence;
    //相对于l_whence的偏移量,单位是byte
    off_t l_start;
    //区域的字节长度
    off_t l_len;
    //进程ID
    pid_t l_pid;
}

关于该结构需要注意的是:

  1. 锁可以在当前文件尾端处开始或者越过尾端处开始,但是不能在文件起始位置之前开始。
  2. 如果l_len为0,则表示锁的范围可以扩展到最大可能偏移量,不管向该文件中追加多少数据,都处于锁的范围内,而且起始位置可以是文件中的任意一个位置。
  3. 为了对整个文件加锁,我们设置l_start和l_whence指向文件的起始位置,指定l_len为0.
  4. 多个进程访问同一文件,只有读锁+读锁可以兼容,但单个进程对同一区间重复加锁的结果是后面的锁覆盖前面的锁。

cmd参数决定函数fcntl的行为,其可选值如下:

  1. F_GETLK:判断是否可以对文件加锁。(很少用)
  2. F_SETLK:加锁。出错则立即返回,非阻塞。
  3. F_SETLKW:F_SETLK的阻塞版本,当不能加锁时进程会休眠等待,直到锁可用或收到中断信号时被唤醒。

注意F_GETLK与FSETLK不是原子操作,在两个函数调用之间可能有新的进程进行了加锁操作。在设置或释放文件上的一把锁时,系统会按要求组合或分裂相邻区。

记录锁在使用过程中也可能会造成死锁,需要当心。

3.2 锁的隐含继承和释放

记录锁的自动继承和释放有3条规则:

3.2.1 锁与进程和文件两者相关联

  1. 锁与进程的联系:当一个进程终止时,它所建立的锁全部释放。
  2. 锁与文件的联系:无论一个描述符何时关闭,该进程通过这一描述符引用的文件上的任何一把锁都会释放。

3.2.2 由fork产生的子进程不继承父进程的锁

若一个进程得到一把锁,然后调用fork,那么对于父进程获得的锁而言,子进程被视为另一个进程。

3.2.3 在执行exec后,新程序可以继承原执行程序的锁

p3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值