当前位置: 首页 > article >正文

Linux五种IO模型和fctnl的使用

input / output :访问外设

recv:大部分时间是在等,一部分时间是在真正做IO : IO = 等 + 拷贝

由于IO大部分时间是在等待的,那么要高效IO,单位时间去减少等的时间。

如何提高IO的效率——减少单位时间等的比重

5种IO模型

例子:钓鱼

钓鱼=等+ 钓

河:OS 鱼 :数据 钓:数据就绪条件 鱼竿:文件描述符

1.张三:只看着鱼漂,谁叫都不理。 阻塞式IO 80%+等待 同步IO

2.李四:一会看鱼漂,一会玩手机 非阻塞式轮询IO VS阻塞式IO :等的方式不同 同步IO

3.王五:铃铛绑在鱼竿上,当铃铛响了,自己知道应该去收杆了 信号驱动式IO(SIGIO)王五钓鱼的时候需要自己做 同步IO

4.赵六:放置200个鱼竿,一遍一遍遍历200个鱼竿 钓鱼效率最高 多路复用 同步IO

5.田七:发起了钓鱼,但自己干别的事去了。让小王去钓鱼 异步IO

同步IO:只要参与IO的过程(等或拷贝)就是同步IO

阻塞IO

非阻塞IO

底层数据没准备好,不会阻塞住,而是返回一个值告诉进程数据没准备好,此时进程可以做其他事情。

信号驱动IO

多路转接 IO高效

操作系统提供了一个特定的系统调用select,select一次可以等待多个文件描述符,它处理的是IO中等的过程

一旦数据准备好了,recvfrom就可以立即参与拷贝,从内核拷贝到用户。

异步IO

非阻塞IO-fcntl

实现非阻塞

先获取该文件描述符的文件状态标记

再去设置文件状态设置为非阻塞模式 O_NONBLOCK

tips:系统IO函数通常要对,sizeof(buffer)-1,而c语言的IO函数不用减一,因为它自身会对字符串做处理

如果以非阻塞方式读,不会被read阻塞住,返回值以出错的值-1返回,

我们是需要将read错误和read非阻塞的情况靠errno区分开的

便于我们对这两种情况做不同的处理

if(errno==EAGAIN || errno == EWOULDBLCOK)

{

  //TO DO other work

}

else

{

cerr<< "read errno"<<errno<< strerrno(errno)<<endl;

}

被信号中断 IO中断

标准的写法中 还要写入

else if(errno==EINTR) // 这种也不是read出错了

未设置非阻塞:光标一直等待我们输入,代码阻塞在read函数上。

设置非阻塞,可以看到运行中并没阻塞在read函数上,而是一直在做其他事

​代码

#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
using namespace std;
void SetNoBlock(int fd)
{
    int fl=fcntl(fd,F_GETFL);
    if (fl<0)
    {
        cerr<<"fcntl error"<<errno<<strerror(errno)<<endl;
        return;
    }
    fcntl(fd,F_SETFL,O_NONBLOCK|fl);
}
int main()
{
    char  buffer[1024];
    SetNoBlock(0);
    while (true)
    {
        int n =read(0,buffer,sizeof(buffer)-1);
        if(n>0)
        {
           buffer[n]=0;
           cout<<"read info: "<<buffer<<endl;
        }
        else if(n==0)
        {
            cout<<"read finish"<<endl;
            break;
        }
        else
        {
            if(errno==EAGAIN || errno== EWOULDBLOCK)
            {
                //非阻塞
                cout<<"do other thing"<<endl;
                sleep(1);
                continue;
            }
            else if(errno = EINTR)
            {
                //信号中断
                break;
            }
            else
            {
                //出错
                 cerr<<"read error"<<errno<<strerror(errno)<<endl;
                break;
            }
        }
    }
  
   
}

http://www.kler.cn/a/388995.html

相关文章:

  • adb shell常用命令
  • 欧国联的规则,你都了解吗?
  • ESLint 使用教程(七):ESLint还能校验JSON文件内容?
  • 【CICD】GitLab Runner 和执行器(Executor
  • 【Linux】基础IO及文件描述符相关内容详细梳理
  • Django 详细入门介绍
  • [护网杯 2018]easy_tornado
  • 中国药品注册审批数据库- 药品注册信息查询与审评进度查询方法
  • 《deep learning for AI》文献翻译及总结
  • DICOM(数字成像和通信医学)简介 【C#】
  • 移动应用开发:简易登录页
  • 用redis实现签到功能
  • 屏幕后期处理
  • 深度学习之卷积问题
  • Flutter鸿蒙next 使用 BLoC 模式进行状态管理详解
  • 【Axure视频教程】多选按钮控制元件显示和隐藏
  • 汽车共享管理:SpringBoot技术深度解析
  • 【Spring 框架】初识 Spring
  • 鸿蒙系统:安卓与iOS的强劲对手
  • Python与Excel交互:pandas库安装及基本用法
  • 专业140+总分410+东北大学841考研经验东大电子信息与通信工程通信专业基础真题,大纲,参考书
  • SPIRE: Semantic Prompt-Driven Image Restoration 论文阅读笔记
  • ThingsBoard规则链节点:Clear Alarm节点详解
  • Spark SQL大数据分析快速上手-DataFrame应用体验
  • jmeter常用配置元件介绍总结之用linux服务器压测
  • 如何让ffmpeg运行时从当前目录加载库,而不是从/lib64