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

liunx io模型多路复用

多路复用

应用程序中同时处理多路输入输出流,若采用阻塞模式,得不到预期的目的;

若采用非阻塞模式,对多个输入进行轮询,但又太浪费CPU时间;

若设置多个进程/线程,分别处理一条数据通路,将新产生进程/线程间的同步与通信问题,使程序变得更加复杂;

 比较好的方法是使用I/O多路复用技术。其(select)基本思想是:

 1.先构造一张有关描述符的表(最大1024),然后调用一个函数。

 2.当这些文件描述符中的一个或多个已准备好进行I/O时函数才返回。

3. 函数返回时告诉进程哪个描述符已就绪,可以进行I/O操作。

select

通过man手册得到函数的用法及参数:

int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);

功能:

实现IO的多路复用

参数:

nfds:关注的最大的文件描述符+1

readfds:关注的读表

writefds:关注的写表

exceptfds:关注的异常表

timeout:超时的设置

编程步骤:

  1. 构造一张关于文件描述符的表
  2. 清空表 FD_ZERO
  3. 将关心的文件描述符添加到表中 FD_SET
  4. 调用select函数,监听 select
  5. 判断到底是哪一个或者是哪些文件描述符发生了事件 FD_ISSET
  6. 做对应的逻辑处理 

通过代码实现:输入鼠标的时候, 响应鼠标事件, 输入键盘的时候, 响应键盘事件 (两路IO)


#include <stdio.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

int main(int argc, char const *argv[])
{
    char buf[128] = {0}; // 用于存储读取的数据
    int fd = open("/dev/input/mouse0", O_RDONLY); // 打开鼠标设备文件
    if (fd < 0)
    {
        perror("open err"); // 打开文件出错
        return -1;
    }

    fd_set rfds; // 文件描述符集合
    while (1)
    {
        FD_ZERO(&rfds); // 清空文件描述符集合
        FD_SET(fd, &rfds); // 将鼠标设备的文件描述符加入集合
        FD_SET(STDIN_FILENO, &rfds); // 将标准输入的文件描述符(键盘)加入集合

        // 监听文件描述符是否有可读事件
        int ret = select(fd + 1, &rfds, NULL, NULL, NULL);
        if (ret < 0)
        {
            perror("select err"); // select 出错
            close(fd);
            return -1;
        }

        // 检查标准输入是否有数据可读
        if (FD_ISSET(STDIN_FILENO, &rfds))
        {
            fgets(buf, sizeof(buf), stdin); // 从标准输入读取数据
            printf("键盘输入: %s\n", buf);
        }

        // 检查鼠标设备是否有数据可读
        if (FD_ISSET(fd, &rfds))
        {
            ssize_t n = read(fd, buf, sizeof(buf)); // 从鼠标设备读取数据
            if (n < 0)
            {
                perror("read err"); // 读取设备出错
            }
            else
            {
                printf("鼠标数据: ");
                for (ssize_t i = 0; i < n; ++i)
                {
                    printf("%02x ", (unsigned char)buf[i]); // 以十六进制打印鼠标数据
                }
                printf("\n");
            }
        }

        memset(buf, 0, sizeof(buf)); // 清空缓冲区
    }
    close(fd); // 关闭文件描述符

    return 0;
}


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

相关文章:

  • 果然,秋招会惩罚每一个本末倒置的应届生
  • 启动与登录Mysql
  • JS_对象的创建
  • 防近视护眼台灯什么牌子好?五款防近视效果好的护眼台灯推荐
  • 春日美食家:SpringBoot网上订餐系统
  • 使用PowerShell连接国际版Exchange Online合规保护
  • Vue3 动态组件
  • LeetCode 热题 100 回顾
  • c#中Graphics常用的属性
  • 十二、C语言:内存函数
  • matlab数据批量保存为excel,文件名,行和列的名称设置
  • 0基础跟德姆(dom)一起学AI Python进阶08-生成器,property关键字,正则表达式
  • Python 全栈系列268 数据库浅析
  • PHP Redis扩展详解
  • 智慧驱动,效能跃升 | 华宇市场监管现场执法数智助手
  • CentOS 7.9 安装
  • Vue 介绍与体验
  • 概率DP (由一道绿题引起的若干问题。目前为一些老题,蒟蒻的尝试学习1.0)
  • Docker Elasticsearch安装ik分词插件教程
  • LinuxQt下的一些坑之一