Linux驱动IO篇——IO多路复用

news2024/11/26 20:19:48

在这里插入图片描述

文章目录

    • 什么是IO多路复用
    • IO多路复用的三种方法
    • select
    • poll
        • poll系统调用过程
        • 驱动中poll机制实现

什么是IO多路复用


简单来说,就是解决能够同时操作多个设备的方法,及时处理多个设备的数据。

具体的,是指单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力。

IO多路复用的三种方法


Linux的IO多路复用有三种方法:selectpollepoll,且这三种方法都是系统调用

这里介绍嵌入式中常用的两种selectpoll

select

相关接口

/* According to POSIX.1-2001, POSIX.1-2008 */
    #include <sys/select.h>

    /* According to earlier standards */
    #include <sys/time.h>
    #include <sys/types.h>
    #include <unistd.h>

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

    int pselect(int nfds, fd_set *readfds, fd_set *writefds,
                fd_set *exceptfds, const struct timespec *timeout,
                const sigset_t *sigmask);

    
    int  FD_ISSET(int fd, fd_set *set);
    void FD_SET(int fd, fd_set *set);
	void FD_CLR(int fd, fd_set *set);
    void FD_ZERO(fd_set *set);

``select把要监视的文件描述符分成三类:readfdswritefdsexceptfds`。

readfds是需要进行读操作的文件描述符,writefds是需要进行写操作的文件描述符,exceptfds是需要进行异常处理的文件描述符。对于不需要监听的,填NULL即可。

第一次对n个文件进行select()的时候,若任何一个文件满足要求,select()就直接返回;第2次再进行select()的时候,没有文件满足读写要求,select()的进程阻塞且睡眠。示意图如下:

在这里插入图片描述

fd_set是文件描述符组,需要通过FD_XX系列的函数来操作。例如:

FD_ZERO:清空文件描述符组

fd_set writefds;
FD_ZERO(&writefds)

FD_SET:添加一个文件描述符到组中

FD_CLR:删除一个组中的文件描述符

FD_SET(fd, &writefds);//将fd加进组中
FD_CLR(fd, &writefds);//将fd从组中删除

FD_ISSET:检测一个文件描述符是否在组中,我们用这个来检测一次select调用之后有哪些文件描述符可以进行IO操作

if (FD_ISSET(fd, &readfds)){
  /* fd可读 */
}

poll


#include <poll.h>
int poll(struct pollfd fds[], nfds_t nfds, int timeout)

poll()函数也是一个系统调用,可实现类似select()的效果。与select()不同的是,select将要监听的文件描述符分为读、写、异常三种,而poll则使用一个文件描述符集struct pollfd fds[]来管理。

struct pollfd用来描述一个需要监听的文件描述符,传参时传入struct pollfd类型数组fds。

参数说明

参数说明
fds一个struct pollfd结构类型的数组,用于存放需要检测其状态的文件描述符集;
nfds用于标记数组fds中的结构体元素的总数量
timeout阻塞的时间,单位:毫秒;如果timeout==0,那么poll() 函数立即返回而不阻塞,如果设置为负数,那么poll() 函数会一直阻塞下去,直到所检测的文件描述符上的感兴趣的事件发生是才返回。

返回值

  • >0:数组fds中准备好读、写或出错状态的那些文件描述符的总数量
  • ==0:代表poll超时
  • -1:代表poll函数调用失败,同时会自动设置全局变量errno

struct pollfd结构体

struct pollfd{
    int fd; /*文件描述符*/
    short events; /* 等待的需要测试事件 */
    short revents; /* 实际发生了的事件,也就是返回结果 */
}

events和revents事件值

常量说明
POLLIN普通或优先级带数据可读
POLLRDNORM普通数据可读
POLLRDBAND优先级带数据可读
POLLPRI高优先级数据可读
POLLOUT普通数据可写
POLLWRNORM普通数据可写
POLLWRBAND优先级带数据可写
POLLERR发生错误
POLLHUP发生挂起
POLLNVAL描述字不是一个打开的文件

poll系统调用过程

poll系统调用在内核中的入口函数是sys_poll()sys_poll()的系统调用关系如下:

在这里插入图片描述

关键点是在vfs_poll()函数:

//include/linux/poll.h

static inline __poll_t vfs_poll(struct file *file, struct poll_table_struct *pt)
{
	if (unlikely(!file->f_op->poll))
		return DEFAULT_POLLMASK;
	return file->f_op->poll(file, pt);//调用到驱动中的poll函数
}

file->f_op->poll(file,pt)会调用到驱动中的poll函数.

驱动中poll机制实现

驱动中只需要实现struct file_operations结构体里的poll函数,代码如下:

static unsigned int my_poll(struct file *fp, struct poll_table_struct *wait)
{
	unsigned int mask = 0;
    poll_wait(fp, &btn_waitq, wait);//将驱动中的等待队列btn_waitq添加进等待队列表table中
    if(ev_press)
        	mask |= POLLIN|POLLRDNORM;
	return mask;
}

static struct file_operations my_fops = {
    .owner = THIS_MODULE,
    ......
    .poll = my_poll,
};	

应用程序调用poll()时,内核中会调用每个设备驱动中的poll函数,这些底层函数都会调用poll_wait()将本设备驱动中的等待队列添加到一个等待队列表中(table)

如果监控设备没有事件发生,在调用完所有要监控设备驱动的poll函数后,进程会休眠(table)

如果任何一个监控的设备有事件发生,内核中的poll又会重新带调用每个设备驱动中的poll方法。看看有多少个设备有事件发生,然后才返回到应用层。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1014625.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据在内存中的存储——练习4

题目&#xff1a; int main() {char a[1000];int i;for(i0; i<1000; i){a[i] -1-i;}printf("%d",strlen(a));return 0; }思路分析&#xff1a; 已知条件&#xff1a; 通过循环遍历&#xff0c;我们得到的结果是 -1、-2、-3、-4等等。这些是数组内部的存储的元…

R 语言的安装教程

一、下载相关软件 1、R 下载 官网&#xff1a;R: The R Project for Statistical Computing 找到中国镜像&#xff0c;下载快 历史版本点击这里 2、Rtools 下载 进入镜像后&#xff0c;点击这里 然后选择与上面下载的R版本相对应的版本即可 3、Rstudio 下载 官网&#xff1…

代码随想录算法训练营Day59 | 503. 下一个更大元素II | 42. 接雨水

文章目录 503. 下一个更大元素II42. 接雨水暴力解法双指针优化单调栈单调栈的处理逻辑 503. 下一个更大元素II 题目链接 | 解题思路 本题和每日温度非常相似&#xff0c;只是需要循环数组。最简单的方法当然是直接拼接数组&#xff0c;然后直接使用单调栈&#xff0c;最后修改…

搭建Jaeger

本篇是对 Golang 上手GORM V2 Opentracing链路追踪优化CRUD体验&#xff08;源码阅读&#xff09;[1] 阅读与实践 该篇相关代码[2] GORM V2版本开始支持Context上下文传递&#xff0c;支持插件Plugins(有了插件&#xff0c;callback和hook的代码就能更优雅一点) ORM利用反射&a…

Seata1.5.2解决分布式事务问题

分布式事务–Seata ​ 前面了解到一些分布式事务的解决方案&#xff0c;业内也涌现出不少解决分布式事务的优秀框架&#xff0c;如Atomikos、Seata等&#xff0c;本章来了解使用下Seata。 ​ Seata的前身是Fescar&#xff0c;而后改名Seata&#xff0c;简单可扩展的自治分布式…

性能工程全景图、实施方案、建设目标

性能工程是一个关注系统性能层面的体系,包含测试环境的性能测试、生产环境的性能测试、性能调优、容量规划等多个方面 性能工程主要包括如下3个部分 ❑建设性能测试理论体系和流程规范、链路分析基础知识体系和流程规范、性能调优基础理论体系和流程规范。 ❑搭建高效协同的工…

js通过xpath定位元素并且操作元素以下拉框select为例

js也可以使用xpath定位元素&#xff0c;现在实例讲解。 页面上有一个下拉框&#xff0c;里面内容有三个&#xff0c;用F12看一下 一、使用xpath定位这个下拉框select eldocument.evaluate(//select[name"shoppingPreference"], document).iterateNext()二、为下拉框…

代码随想录算法训练营Day60 | 84. 柱状图中最大的矩形

文章目录 84. 柱状图中最大的矩形首尾加 0双指针 84. 柱状图中最大的矩形 题目链接 | 解题思路 本题和接雨水的题目相互呼应&#xff0c;但是难度略有提升&#xff0c;同样是一道非常棒的题&#xff01; 在接雨水中&#xff0c;需要找到每一列的左侧最大值和右侧最大值&…

高阶数据结构(2)-----红黑树

一)红黑树的基本概念和基本性质: 1)红黑树就是一种高度平衡的二叉搜索树&#xff0c;但是在每一个节点上面都增加了一个存储位来表示结点的颜色&#xff0c;可以是红色或者是黑色&#xff0c;通过对任何一条从根节点到叶子节点上面的路径各个节点着色方式的限制&#xff0c;红黑…

Selenium+Pytest自动化测试框架实战(下)

前言 本文接上篇文章哟。 一、简单学习元素定位 在日常的工作中&#xff0c;我见过很多在浏览器中直接在浏览器中右键Copy Xpath复制元素的同学。这样获得的元素表达式放在 webdriver 中去运行往往是不够稳定的&#xff0c;像前端的一些微小改动&#xff0c;都会引起元素无法…

Truenas scale 安装 Tailscale 内网穿透远程连接SMB服务

起源 没有公网IP&#xff0c;不在同一个路由器&#xff0c;没法远程连接电脑或者服务器。之前一直使用 zerotier&#xff0c; 但是这次使用 Truenas scale 安装 zerotier&#xff0c; 每次重启都变化IP&#xff0c;一直没解决。转投 tailscale。 注册 YouTube有教程&#xf…

基于ssm智能停车场031

大家好✌&#xff01;我是CZ淡陌。一名专注以理论为基础实战为主的技术博主&#xff0c;将再这里为大家分享优质的实战项目&#xff0c;本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#xff0c;希望你能有所收获&#xff0c;少走一些弯路…

安装并设置linux虚拟机ubuntu20.04.6 LTS

1 安装虚拟机 1、安装虚拟机模拟软件virtualboxhttps://download.virtualbox.org/virtualboxhttps://download.virtualbox.org/virtualbox/7.0.10/VirtualBox-7.0.10-158379-Win.exe 2、在virtualbox中安装虚拟机ubuntu 20.04.6 LTS 桌面版https://www.releases.ubuntu.com/fo…

进度条--QProgressBar,进度对话框--QProgressDialog

一、QProgressBar 进度条 1、QProgressBar 类继承自 QWidget&#xff0c;它是一个 QWidget 部件&#xff0c; QProgressBar 除了将其放置 于进度对话框之中外&#xff0c;还可将其放置于窗口的状态栏等其他部件中。 QProgressBar提供了一个水平或垂直的进度条&#xff0c;可以…

JDBC基本概念

什么是JDBC JDBC概念 JDBC&#xff08;Java DataBase Connectivity&#xff09;是一套统一的基于Java语言的关系数据库编程接口规范。 该规范允许将SQL语句作为参数通过JDBC接口发送给远端数据库&#xff0c; …

8位和32位单片机如何选择适合,以及主要区别!

单片机直接影响到项目的成功和性能&#xff0c;我们将分享如何选择适合您的应用的8位或32位单片机。 8位单片机 vs. 32位单片机&#xff1a; 一、性能和处理能力&#xff1a; 8位单片机&#xff1a; 8位单片机通常适用于相对简单的应用&#xff0c;如传感器控制、LED显示、小…

代码随想录算法训练营第三十五天| 860.柠檬水找零 406.根据身高重建队列 452. 用最少数量的箭引爆气球

860.柠檬水找零 本题看上好像挺难&#xff0c;其实挺简单的&#xff0c;大家先尝试自己做一做。 代码随想录 public boolean lemonadeChange(int[] bills) {int five 0;int ten 0;for (int i 0; i < bills.length; i) {if (bills[i] 5) {five;} else if (bills[i] 10)…

Mysql同步数据到Doris的踩坑过程

问题背景 由于项目需要&#xff0c;需要把多个Mysql数据库的数据同步到Doris数据库&#xff0c;然后利用Doris强调的计算和查询能力&#xff0c;来满足业务需求。有关Doris可以查看它的官方文档来了解它。 seatunnel的使用到放弃 缘起 从《第十届GIAC全球互联网架构大会》了…

论如何在Android中还原设计稿中的阴影

每当设计稿上注明需要添加阴影时&#xff0c;Android上总是显得比较棘手&#xff0c;因为Android的阴影实现方式与Web和iOS有所区别。 一般来说阴影通常格式是有&#xff1a; X: 在X轴的偏移度 Y: 在Y轴偏移度 Blur: 阴影的模糊半径 Color: 阴影的颜色 何为阴影 但是在A…

手刻 Deep Learning -第壹章 -PyTorch教学-激励函数与感知机入门(上)

一、前言 本文接续前篇教学 Pytorch 与线性回归 &#xff0c;本文着重在 Activation Function &#xff08; 中文称 激励函数 &#xff09;&#xff0c;我们会介绍激励函数 &#xff08;也有人称 激活函数&#xff1f; 激发函数&#xff1f; &#xff09; 为什么会有用&#xf…