• 1.5 阻塞与非阻塞I/O


    1、阻塞I/O

    在这里插入图片描述

    阻塞和非阻塞主要是指这个函数,是否会导致我们这个进程进入sleep休眠。
    阻塞:这种函数,会导致进程进入休眠,在等待一个动作发生才会继续走下去,这种阻塞不好,效率很低

    2、非阻塞I/O

    在这里插入图片描述

    不会卡住,充分利用CPU时间片,不断的调用accept和recvfrom函数来查看有没有数据到来,通过标记来进行判断,如果数据到来,那么就会卡着,将内核缓存区的数据拷贝到用户缓存区。

    3、异步I/O

    在这里插入图片描述

    调用一个异步I/O函数,要给这个函数指定一个缓存区,还需要一个回调函数,其他事情交给操作系统,调用完一个异步I/O函数会立即返回,操作系统会判断数据是否到来,来了就会将数据拷贝到缓存区中,调用指定回调函数来通知你。

    和非阻塞的差别:需要不停的调用I/O函数,如果数据来就会卡在I/O函数这,就会将数据从内核缓存区复制到用户缓存区,异步I/O不需要不停的调用,只需要调用一次,然后可以去执行其他事情,通过内核检查数据是否到来,在整个过程中没有卡顿

    4、同步I/O

    在这里插入图片描述

    1、select先判断数据有没有,没数据卡在那里,有数据返回之后,用recvfrom去读取数据(还是会卡一下,取数据的时候,将内核缓存区拷贝到用户缓存区),更麻烦,需要调用两个函数才能拿到数据,所谓I/O复用,就是我可以同步等待多个socket的数据,任意一个socket上面有数据了我就去recvfrom去读

    5、epoll原理函数

    在这里插入图片描述

    5.1、int epoll_create(int size)

    1、int epoll_create(int size);
    参数:
        size 创建的红黑树的监听数据节点(数目最大有多大,从Linux 2.6.8开始,max_size参数将被忽略,但必须大于零。)
    返回值:
        成功 指向新创建的红黑树的根节点fd
        失败 -1 errno
    作用:创建一颗空红黑树和一个双向空链表
    
    
    流程:
    1、开辟了一块eventpoll结构类型的内存
    	结构中成员rbr指向,一颗红黑树的根节点
    	结构中成员rdlist指向,双向链表的头指针
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    5.2、int epoll_ctl(int epfd,int op,int fd,struct epoll_event* event)

    2int epoll_ctl(int epfd,int op,int fd,struct epoll_event* event);
    参数:
        epfd: epoll_create 函数的返回值
        op: 对该监听的红黑树操作
            EPOLL_CTL_ADD   添加fd到 监听红黑树
            EPOLL_CTL_MOD   修改fd在监听红黑树上的监听事件
            EPOLL_CTL_DEL   将一个fd从监听红黑树上摘下(取消监听)
        fd:待监听的fd文件描述符
        event:结构体的地址
            struct epoll_event {
                uint32_t     events;      
                // EPOLLIN / EPOLLOUT / EPOLLERR
                epoll_data_t data;    
                // fd 对应监听事件的fd
                // void* ptr
                // u32
                // u64
            };
            typedef union epoll_data {
                    void        *ptr;
                    int          fd;
                    uint32_t     u32;
                    uint64_t     u64;
            } epoll_data_t;
    返回值:
        成功 0
        失败 -1 errno
    作用:把一个socket以及这个socket相关的事件添加到epoll对象描述符中,目的通过epoll来监听这个socket,有感兴趣的事件来了通知我们
    
    
    流程:
    1、EPOLL_CTL_ADD   添加
    生成红黑树的节点,epitem结构体,将socket保存到节点中、作为红黑树的key,添加的事件也保存进去
    	成员:rbn结构体包含三个指针,左、右、父节点的指针
    	成员:rblist结构体包含:指向前一个元素,后元素的指针
    
    2、EPOLL_CTL_DEL  删除
    a)通过socket到红黑树中进行查找,
    b)有就把这个节点删除
    
    3、EPOLL_CTL_DEL  修改
    a)通过socket到红黑树中进行查找
    b)找到红黑树节点修改红黑树事件
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    5.3、int epoll_wait(int epfd,struct epoll_event* events,int maxevents,int timeout)

    int epoll_wait(int epfd,struct epoll_event* events,int maxevents,int timeout);
    参数:
        epfd:epoll_create 函数返回值 epfd
        events:传出参数【数组】,满足监听条件的
        maxevents:数组 元素的总个数1024
        timeout:毫秒
            -1 阻塞
            0 不阻塞
            >0  超时事件(毫秒)
    返回值:
        >0 满足监听的总个数,可以用作循环上限
        0 没有fd满足条件
        -1 errno
    作用:阻塞一小段时间,等待事件发生,返回事件集合,也就是获取内核的事件通知(遍历双向链表,把双向链表数据拷贝出去,拷贝完毕,移除)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    5.4、内核向双向链表增加节点

    总结:红黑树的节点是通过EPOLL_CTL_ADD添加进去的。
    一般用四种情况,操作系统会把节点添加到红黑树上:
    1、客户端完成三次握手,服务端要accept()
    2、客户端关闭连接时候,服务器调用close()
    3、到客户端发送数据,服务器调用read()
    4、当可以发送数据时,服务器调用write()

    6、Linux命令

    # 查看有哪些进程监听80端口
    lsof -i:80 
    
    
    • 1
    • 2
    • 3
  • 相关阅读:
    Qt之解析HTML
    MySQL(4)
    云原生多云容器编排平台karmada上手指南
    Golang反射获取变量类型和值
    世界上第一个“半机械人”去世,改造自己只为“逆天改命”
    2022年中职组网络安全新赛题
    (上)unity教程之UnityPath-Dream从小白到大神
    小程序源码:超强大教育培训学校源码微信小程序源码下载,带课件/习题/活动插件,支持小程序与公众号双版本
    算法练习-LeetCode 剑指 Offer 33. 二叉搜索树的后序遍历序列
    node18 vue2启动报错 error:0308010C:digital envelope routines::unsupported
  • 原文地址:https://blog.csdn.net/weixin_45715405/article/details/127643972