【Linux】第十六章 高级IO (五种IO模型+fcntl)



IO主要分为两步:

  • 第一步是等,即等待IO条件就绪。
  • 第二步是拷贝,也就是当IO条件就绪后将数据拷贝到内存或外设。

让IO变得高效,最核心的办法就是尽量减少“等”的时间

五种 IO 模型

  • A, 拿着鱼竿去钓鱼,一直盯着鱼漂,鱼漂有动静就收钩

  • B, 拿着鱼竿去钓鱼,时不时看看鱼漂,有动静就收购

  • C, 拿着鱼竿去钓鱼,在鱼漂上弄个铃铛,然后干其他的事情,听到铃铛的声音就收钩

  • D, 拿了一大堆鱼竿过来,都摆弄好,只要有一个鱼漂有动静,就收钩

  • E 是大老板,直接叫人帮忙钓鱼,钓到一定数量的🐟后通知自己,自己过来取🐟

    这五种钓鱼方式,就对应了五种 IO 模型

  • A, 阻塞等待 , 等待到数据就立即读取

  • B, 轮询检测 , 检测到数据的时候读取

  • C, 利用铃铛来作为通知方式,听到了信号之后,就去读取数据(信号驱动

  • D, 一次性检测多个文件描述符(多路转接

  • E, 没有自己参与钓鱼过程,有别人帮忙监控文件描述符,自己只关心拿走数据(异步 IO

ABC效率本质上是一样,D 的效率是最高的,ABCD是同步IO

异步IO 和 同步IO

  • 异步IO没有参与IO细节,不需要你进行“等”和“拷贝”的操作
  • 同步IO有参与IO细节

同步通信 和 异步通信

  • 异步通信:在调用发出后,这个调用直接返回,并没有携带结果
  • 同步通信:在发出调用后,没有得到结果前,该调用不返回

同步通信 和 同步与互斥

  • 线程和进程的同步指的是线程和进程之间有相互制约的关系,让进程/线程能够按照某种特定的顺序访问临界资源
  • 而同步IO指的是进程/线程与操作系统之间的关系,谈论的是进程/线程是否需要主动参与IO过程

fcntl-设置非阻塞IO

默认创建的都是阻塞的文件描述符,我们可以使用 fcntl 来将文件描述符设置成非阻塞的

#include <unistd.h>
#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */ );
  • 复制一个现有的描述符(cmd=F_DUPFD)
  • 获得 / 设置文件描述符标记 (cmd=F_GETFD 或 F_SETFD)
  • 获得 / 设置文件状态标记 (cmd=F_GETFL 或 F_SETFL)
  • 获得 / 设置异步 I/O 所有权 (cmd=F_GETOWN 或 F_SETOWN)
  • 获得 / 设置记录锁 (cmd=F_GETLK, F_SETLK 或 F_SETLKW)
  • … 可变参数,传入的cmd值不同,后面追加的参数也不同。

返回值

  • 如果函数调用成功,则返回值取决于具体进行的操作。
  • 如果函数调用失败,则返回-1,同时错误码会被设置。

测试

定义一个函数,该函数就用于将指定的文件描述符设置为非阻塞状态

bool SetNonBlock(int fd)
{
    	//传入的cmd值为F_SETFL,获取文件已有状态
	int fl = fcntl(fd, F_GETFL);
	if (fl < 0){
		std::cerr << "fcntl error" << std::endl;
		return false;
	}
    	//添加非阻塞标记O_NONBLOCK
	fcntl(fd, F_SETFL, fl | O_NONBLOCK);
	return true;
}

stdin(0号文件描述符)输入的时候,进程就是处于阻塞状态,等待输入,如果我们改成非阻塞,那么stdin不会阻塞

int main()
{
    SetNoBlock(stdin->_fileno);
    char buf[1024];
    while(true)
    {
        ssize_t read_size = read(stdin->_fileno, buf, sizeof(buf) - 1);
        if(read_size < 0)
        {
            perror("read err");
            sleep(2);
            continue;
        }
        printf("input:%s\n", buf);
        buf[0] = '\0';
    }
    return 0;
}

没有输入就会一直循环打印报错,如果有输出内容就会把输出内容打印

read err: Resource temporarily unavailable
read err: Resource temporarily unavailable
read err: Resource temporarily unavailable
read err: Resource temporarily unavailable
123
input:123

read err: Resource temporarily unavailable

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

penguin_bark

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值