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;
}

  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值