爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      ldd3学习之十二(3):高级字符驱动程序操作--poll/select、异步通知

      首页 知识中心 软件开发 文章详情页

      ldd3学习之十二(3):高级字符驱动程序操作--poll/select、异步通知

      2023-05-11 06:05:48 阅读次数:496

      ldd3,select

      1.select

      能够监听多个阻塞的文件描述符,这样,不需要fork和多进程就可以实现并发服务(网络中常用来监听多个网络连接)。

      原型

      1. #include <sys/select.h>
      2. {
      3. ; /* seconds */
      4. ; /* and microseconds */
      5. };
      6.  
      7. int select(int maxfdp1,
      8. *restrict readfds,
      9. *restrict writefds,
      10. *restrict exceptfds,
      11. *restrict tvptr);

      maxfdp1:select中监视的文件句柄数,一般设为要监视的文件中的最大文件号加一。

      readfds:select()监视的可读文件句柄集合,当readfds映象的文件句柄状态变成可读时系统诉select函数返回。这个集合中有一个文件可读,select0timeouttimeoutselect0,若发生错误返回负值,可以传入NULL值,表示不关心任何文件的读变化;

      writefds:监视的可写文件句柄集合,当writefds映象的文件句柄状态变成可写时系统告诉select函数返回。如果这个集合中有一个文件可写,select就会返回一个大于0的值,表示有文件可写,如果没有可写的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值,可以传入NULL值,表示不关心任何文件的写变化。

      exceptfds:select()监视的异常文件句柄集合,当exceptfds映象的文件句柄上有特殊情况发生时系统会告诉select函数返回。

      tvptr:select()的超时结束时间。

      这个参数它使select
      第一,若将NULL以形参传入,即不传入时间结构,就是将select阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止;
      第二,若将时间值设为00毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;
      第三,timeout大于0,这就是等待的超时时间,即select在timeout超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回,返回值同上述。

      返回值:

      负值: select 错误0

      :等待超时,没有可读写或错误的文件

      正值:某些文件可读可写或出错

      对文件句柄操作函数

      1. FD_ZERO(fd_set *fdset);//清空fdset与所有文件句柄的联系。
      2. (int fd, fd_set *fdset);//建立文件句柄fd与fdset的联系。
      3. (int fd, fd_set *fdset);//清除文件句柄fd与fdset的联系。
      4. (int fd, fdset *fdset);//检查fdset联系的文件句柄fd是否可读写,>0表示可读写。

      实例

      1. fd_set readfds;
      2. struct timeval tv;
      3.  
      4. {
      5. FD_ZERO(&readfds);
      6. if(fd>=0)
      7. FD_SET(fd, &readfds);
      8. tv.tv_sec=0;
      9. tv.tv_usec=20*1000;//tv.tv_usec=20*1000;
      10. ret = select((fd+1),&readfds,NULL,NULL,&tv);
      11. }

      2.驱动中轮询的实现

      1. static unsigned int s3c_camif_poll(struct file *file, poll_table *wait)

      第一个参数file这个函数完成两项工作。

      ①对可能引起设备文件状态变化的等待队列调用poll_wait()函数,将对应的等待队列拖添加到poll_table,若没有文件描述符可用来执行I/O,则内核将使进程在传递到该系统调用的所有文件描述符对应的等待队列上等待。

      ②返回表示是否能对设备进行无阻塞读写访问的掩码。

      关键的用于向poll_tablepoll_wait()

      1. static inline void poll_wait(struct file * filp, wait_queue_head_t * queue, poll_table *wait)

      功能:waitpoll_table

      驱动poll()#define POLLIN         0x0001

      #define POLLPRI        0x0002

      #define POLLOUT        0x0004

      #define POLLERR        0x0008

      #define POLLHUP        0x0010

      #define POLLNVAL       0x0020

      Poll函数典型的模板

      1. static unsigned int xxx_poll(struct file *file, poll_table *wait)
      2. {
      3. int mask = 0;
      4. *dev = file->private_data;
      5.  
      6. ...
      7.  
      8. (file, &dev->r_wait, wait);
      9. (file, &dev->w_wait, wait);
      10.  
      11. if (...)//可读
      12. {
      13. |= POLLIN | POLLRDNORM;
      14. }
      15.  
      16. if (...)//可读
      17. {
      18. |= POLLOUT| POLLRDNORM;
      19. }
      20.  
      21. ;
      22. }

      read 和write 的交互

      正确实现poll:

      从设备读取数据:

      ①read poll 应当返回 POLLIN|POLLRDNORM。

      ②readO_NONBLOCK read -EAGIN poll POLLIN|POLLRDNORM③read 0poll POLLHUP向设备写数据

      ①write poll应返回 POLLOUT|POLLWRNORM。

      ②write O_NOBLOCK write -EAGAIN, poll POLLOUT|POLLWRNORM. 若设备不能接受任何多余数据, O_NONBLOCKwrite -ENOSPC("")③writeO_NONBLOCK , fsync 刷新待处理输出
      若一些应用程序需要确保数据被发送到设备,就必须实现fsync方法。对 fsync()即便这需要一些时间,

      1. int (*fsync) (struct file *file, struct dentry *dentry, int datasync);

      参数datasync用于区分fsync和fdatasync两个系统调用,只与文件系统有挂,驱动程序可以忽略。fsync方法对时间没有严格要求,大部分时候,字符驱动中只给个NULL指针,而快设备总是用通用的block_fsync来实现这个方法,block_fsync会依次刷新设备的所有缓冲块,并等待所有I/O结束。

      底层数据结构

      只要用户应用程序调用 poll、select、或epoll_ctl,内核就会调用这个系统调用所引用的所有文件的 poll 方法,并向他们传递同一个poll_table。 poll_table 结构只是构成实际数据结构的简单封装:

      1.  
      1. struct poll_table_struct;
      2. /*
      3. * structures and helpers for f_op->poll implementations
      4. */
      5. (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *);
      6.
      7. {
      8. ;
      9. } poll_table;

      poll和 select系统调用,poll_table 是一个包含 poll_table_entry 结构内存页链表

      1. struct poll_table_entry {
      2. * filp;
      3. ;
      4. * wait_address;
      5. };

      对 poll_wait 的调用有时还会将进程添加到给定的等待队列。整个的结构必须由内核维护,在 poll 或者 select 返回前,进程可从所有的队列中去除, .

      如果被轮询的驱动没有一个驱动程序指明可进行非阻塞I/O,poll 调用会简单地睡眠,直到一个它所在的等待队列(可能许多)唤醒它.

      当 poll 调用完成,poll_table 结构被重新分配, 所有的之前加入到 poll 表的等待队列入口都会从表和它们的等待队列中移出.

      1.  
      1. struct poll_wqueues {
      2. ;
      3. * table;
      4. int error;
      5. int inline_index;
      6. [N_INLINE_POLL_ENTRIES];
      7. };
      8.
      9. {
      10. * next;
      11. * entry;
      12. [0];
      13. };

      4.异步通知

      通过使用异步通知,应用程序可以在数据可用时收到一个信号,而无需不停地轮询。

      启用步骤:

      ①它们指定一个进程作为文件的拥有者:使用 fcntl 系统调用发出 F_SETOWN 命令,这个拥有者进程的 ID 被保存在 filp->f_owner。目的:让内核知道信号到达时该通知哪个进程。

      ②使用 fcntl 系统调用,通过 F_SETFL 命令设置 FASYNC 标志。

      内核操作过程

      ①.F_SETOWN被调用时filp->f_owner被赋值。

      ②. 当 F_SETFL 被执行来打开 FASYNC, 驱动的 fasync 方法被调用.这个标志在文件被打开时缺省地被清除。

      ③. 当数据到达时,所有的注册异步通知的进程都会被发送一个 SIGIO 信号。

      Linux 提供的通用方法是基于一个数据结构和两个函数,定义在 。

      数据结构:

      1.  
      1. struct fasync_struct {
      2. int magic;
      3. int fa_fd;
      4. *fa_next; /* singly linked list */
      5. *fa_file;
      6. };

      驱动调用的两个函数的原型:

      1. int fasync_helper(int fd, struct file *filp, int mode, struct fasync_struct **fa);
      2. (struct fasync_struct **fa, int sig, int band);

      当一个打开的文件的FASYNC标志被修改时,调用fasync_helper 来从相关的进程列表中添加或去除文件。除了最后一个参数, 其他所有参数都时被提供给 fasync 方法的相同参数并被直接传递。 当数据到达时,kill_fasync 被用来通知相关的进程,它的参数是被传递的信号(常常是 SIGIO)和 band(几乎都是 POLL_IN)。

      这是 scullpipe 实现 fasync 方法的:

      1. static int scull_p_fasync(int fd, struct file *filp, int mode)
      2. {
      3. struct scull_pipe *dev = filp->private_data;
      4. return fasync_helper(fd, filp, mode, &dev->async_queue);
      5. }

      当数据到达, 下面的语句必须被执行来通知异步读者. 因为对 sucllpipe 读者的新数据通过一个发出 write 的进程被产生, 这个语句出现在 scullpipe 的 write 方法中:

      1. if (dev->async_queue)
      2. (&dev->async_queue, SIGIO, POLL_IN); /* 注意, 一些设备也针对设备可写而实现了异步通知,在这个情况,kill_fasnyc 必须以 POLL_OUT 模式调用.*/

      当文件被关闭时必须调用fasync 方法,来从活动的异步读取进程列表中删除该文件。尽管这个调用仅当 filp->f_flags 被设置为 FASYNC 时才需要,但不管什么情况,调用这个函数不会有问题,并且是普遍的实现方法。 以下是 scullpipe 的 release 方法的一部分:

      1. /* remove this filp from the asynchronously notified filp's */
      2. (-1, filp, 0);

      异步通知使用的数据结构和 struct wait_queue 几乎相同,因为他们都涉及等待事件。区别异步通知用 struct file 替代 struct task_struct. 队列中的 file 用获取 f_owner,

      1. void input_handler(int num)
      2. {
      3. ("process SIGIO signal.\n");
      4. //system("poweroff");
      5. }
      6. int main(void)
      7. {
      8. int fd, oflags;
      9. = open(DEVICE_NAME, O_RDWR);
      10.
      11. if (fd == -1) {
      12. ("Failed to open alarm device %s\n", DEVICE_NAME);
      13. -1;
      14. }
      15. (SIGIO, input_handler);
      16. (fd, F_SETOWN, getpid());
      17. = fcntl(fd, F_GETFL);
      18.
      19. (fd, F_SETFL, oflags | FASYNC);
      20.
      21. while (1);
      22. ;
      23. }
      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://blog.51cto.com/u_7784550/5677519,作者:luteresa,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:JAVA多线程学习笔记

      下一篇:C Primer Plus 第6版 第4章 编程练习

      相关文章

      2025-05-13 09:50:48

      查找正在执行的select以及dml语句的相关信息

      查找正在执行的select以及dml语句的相关信息

      2025-05-13 09:50:48
      select , session , sql , SQL , 语句
      2025-05-13 09:49:27

      mysql一些小知识点

      mysql 使用的是三值逻辑:TRUE FALSE UNKNOWN。

      2025-05-13 09:49:27
      left , mod , mysql , null , select , user
      2025-04-15 09:19:26

      流程控制_select条件控制_基础实践

      流程控制_select条件控制_基础实践

      2025-04-15 09:19:26
      select , 基础知识 , 实践 , 语法
      2025-04-15 09:18:30

      I/O 多路转接之 poll

      I/O 多路转接之 poll

      2025-04-15 09:18:30
      事件 , 函数 , 描述符
      2025-04-09 09:15:47

      多并发的高实时的订单查询的性能问题(进程内共享数据)

      多并发的高实时的订单查询的性能问题(进程内共享数据)

      2025-04-09 09:15:47
      amp , select , 代码 , 数据库 , 查询 , 索引 , 缓存
      2025-03-31 08:50:08

      multiple select2内置ajax方法的正确使用

      multiple select2内置ajax方法的正确使用

      2025-03-31 08:50:08
      ajax , org , select
      2025-03-28 07:42:42

      SQLServer 数据库sql命令练习

      SQLServer 数据库sql命令练习

      2025-03-28 07:42:42
      select , 截图 , 查询
      2025-03-28 06:50:00

      C#读取shp的属性表dbf文件

      C#读取shp的属性表dbf文件

      2025-03-28 06:50:00
      select , 下载 , 代码 , 读取
      2025-03-26 09:31:12

      Orchestrator 基础测试 (4)

      Orchestrator 基础测试 (4)

      2025-03-26 09:31:12
      34 , select
      2025-03-18 08:27:10

      PostgreSQL9.5.9学习篇布尔类型操作符select查询

      PostgreSQL9.5.9学习篇布尔类型操作符select查询

      2025-03-18 08:27:10
      gt , select
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5249069

      查看更多

      最新文章

      多并发的高实时的订单查询的性能问题(进程内共享数据)

      2025-04-09 09:15:47

      C#读取shp的属性表dbf文件

      2025-03-28 06:50:00

      Orchestrator 基础测试 (4)

      2025-03-26 09:31:12

      Linux网络编程IO管理

      2024-12-05 08:50:14

      JavaScript点击事件实现不同的下拉选择框内容

      2024-04-25 14:12:25

      讲透Go中的并发接收控制结构select

      2023-02-10 10:10:49

      查看更多

      热门文章

      讲透Go中的并发接收控制结构select

      2023-02-10 10:10:49

      JavaScript点击事件实现不同的下拉选择框内容

      2024-04-25 14:12:25

      Linux网络编程IO管理

      2024-12-05 08:50:14

      多并发的高实时的订单查询的性能问题(进程内共享数据)

      2025-04-09 09:15:47

      C#读取shp的属性表dbf文件

      2025-03-28 06:50:00

      Orchestrator 基础测试 (4)

      2025-03-26 09:31:12

      查看更多

      热门标签

      java Java python 编程开发 代码 开发语言 算法 线程 Python html 数组 C++ 元素 javascript c++
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      讲透Go中的并发接收控制结构select

      JavaScript点击事件实现不同的下拉选择框内容

      C#读取shp的属性表dbf文件

      Orchestrator 基础测试 (4)

      Linux网络编程IO管理

      多并发的高实时的订单查询的性能问题(进程内共享数据)

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号