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

Linux学习第24天:Linux 阻塞和非阻塞 IO 实验(一): 挂起

Linux版本号4.1.15   芯片I.MX6ULL                                    大叔学Linux    品人间百味  思文短情长 


        在正式开始今天的笔记之前谈一下工作中遇见的一个问题。

        本篇笔记主要学习Linux 阻塞和非阻塞 IO 实验,主要包括阻塞和非阻塞简介、等待队列、轮询、poll操作、阻塞和非阻塞实验。其中重点内容为阻塞和非阻塞实验。

        本笔记的思维导图如下:

一、阻塞和非阻塞IO

1.阻塞和非阻塞简介

        1)阻塞

1 int fd;
2 int data = 0;
3 4
fd = open("/dev/xxx_dev", O_RDWR); /* 阻塞方式打开 */
5 ret = read(fd, &data, sizeof(data)); /* 读取数据 */

2)非阻塞

1 int fd;
2 int data = 0;
3 4
fd = open("/dev/xxx_dev", O_RDWR); /* 阻塞方式打开 */
5 ret = read(fd, &data, sizeof(data)); /* 读取数据 */

        参数“O_NONBLOCK”,表示以非阻塞方式打开设备,这样从设备中读取数据的时候就是非阻塞方式的了。


2.等待队列

        1)等待队列头

        等待队列头使用结构体wait_queue_head_t 表示:

39 struct __wait_queue_head {
40 spinlock_t lock;
41 struct list_head task_list;
42 };
43 typedef struct __wait_queue_head wait_queue_head_t;

        init_waitqueue_head 函数初始化等待队列头

void init_waitqueue_head(wait_queue_head_t *q)//参数 q 就是要初始化的等待队列头。

也可以使用宏 DECLARE_WAIT_QUEUE_HEAD 来一次性完成等待队列头的定义的初始化。


        2)等待队列项

结构体 wait_queue_t 表示等待队列项,结构体内容如下:

struct __wait_queue {
unsigned int flags;
void *private;
wait_queue_func_t func;
struct list_head task_list;
};
typedef struct __wait_queue wait_queue_t;

        宏DECLARE_WAITQUEUE 就是给当前正在运行的进程创建并初始化了一个等待队列项。

DECLARE_WAITQUEUE(name, tsk)

        name 就是等待队列项的名字, tsk 表示这个等待队列项属于哪个任务(进程),一般设置为
current , 在 Linux 内 核 中 current 相 当 于 一 个 全 局 变 量 , 表 示 当 前 进 程 。

        3)将队列项添加/删除队列头

        只有添加到等待队列头中以后进程才能进入休眠态。等待队列项添加 API 函数如下:

void add_wait_queue(wait_queue_head_t *q,
wait_queue_t *wait)

        等待队列项移除 API 函数如下:

void remove_wait_queue(wait_queue_head_t *q,
wait_queue_t *wait)

        4)等待唤醒

void wake_up(wait_queue_head_t *q)
void wake_up_interruptible(wait_queue_head_t *q)

       wake_up_interruptible 函数只能唤醒处于 TASK_INTERRUPTIBLE 状态的进程。


5)等待事件

函数描述
wait_event(wq, condition)

 
等待以 wq 为等待队列头的等待队列被唤醒,前
提是 condition 条件必须满足(为真),否则一直阻
塞 。 此 函 数 会 将 进 程 设 置 为
TASK_UNINTERRUPTIBLE 状态

 
wait_event_timeout(wq, condition, timeout)
功能和 wait_event 类似,但是此函数可以添加超
时时间,以 jiffies 为单位。此函数有返回值,如
果返回 0 的话表示超时时间到,而且 condition
为假。为 1 的话表示 condition 为真,也就是条
件满足了。

 
wait_event_interruptible(wq, condition)
与 wait_event 函数类似,但是此函数将进程设置
为 TASK_INTERRUPTIBLE,就是可以被信号打
断。

 
wait_event_interruptible_timeout(wq,
condition, timeout)

 
与 wait_event_timeout 函数类似,此函数也将进
程设置为 TASK_INTERRUPTIBLE,可以被信号
打断。

 

3.轮询【非阻塞】

        1)select函数        

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

        fd_set 类型变量的每一个位都代表了一个文件描述符。

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

        2)poll函数

        没有最大文件描述符限制。

int poll(struct pollfd *fds,
nfds_t nfds,
int timeout)

        3)epoll函数

        epoll 就是为处理大并发而准备的。

int epoll_create(int size)

返回值: epoll 句柄,如果为-1 的话表示创建失败。

        epoll_ctl 函数向其中添加要监视的文件描述符以及监视的事件, epoll_ctl 函数原型如下所示:

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

epoll_wait 函数来等待事件的发生:

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

4.poll操作

poll 函数原型如下所示:

unsigned int (*poll) (struct file *filp, struct poll_table_struct *wait)

poll_wait 函数不会引起阻塞,只是将应用程序添加到 poll_table 中, poll_wait 函数原型如下:

void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)

        参数 wait_address 是要添加到 poll_table 中的等待队列头,参数 p 就是 poll_table,就是
file_operations 中 poll 函数的 wait 参数。

二、总结

        本篇笔记主要学习Linux 阻塞和非阻塞 IO 实验,主要包括阻塞和非阻塞简介、等待队列、轮询、poll操作。


以下内容将在下一篇笔记中进行学习:

二、阻塞IO实验

1.硬件原理图分析

2.实验程序

3.运行测试

三、非阻塞IO实验

1.硬件原理图分析

2.实验程序

3.运行测试


本文为参考正点原子开发板配套教程整理而得,仅用于学习交流使用,不得用于商业用途。

http://www.lryc.cn/news/209773.html

相关文章:

  • 037-第三代软件开发-系统音量设置
  • Python 自动化详解(pyautogui)
  • 【Linux】第四站:Linux基本指令(三)
  • SpringBoot内置工具类之断言Assert的使用与部分解析
  • 如何检测租用的香港服务器是不是CN2线路呢?
  • Spring Boot进阶(94):从入门到精通:Spring Boot和Prometheus监控系统的完美结合
  • Redis(02)| 数据结构-SDS
  • HackTheBox-Starting Point--Tier 0---Preignition
  • 售货机相关的电路
  • 软考高项(十四)项目沟通管理 ★重点集萃★
  • Linux多线程服务端编程:使用muduo C++网络库 学习笔记 第五章 高效的多线程日志
  • 利用Pholcus框架提取小红书数据的案例分析
  • 超详细Hadoop安装教程(单机版、伪分布式)
  • 持续集成部署-k8s-服务发现-Ingress
  • 从零开始搭建Prometheus+grafana服务器组件监控系统
  • 智能水厂运行与调控3D模拟仿真在线展示提高整个系统的协同效应
  • ts声明文件
  • JPA联合主键使用
  • 【计算机毕设经典案例】基于微信小程序的图书管理系统
  • 如何制作rpm离线安装包
  • golang中快速用melody搭建轻量的websocket服务
  • ​Profinet转EtherNET/IP从站连接欧姆龙plc与西门子200smart通讯的配置方法​
  • elementUI el-table实现鼠标悬浮某一行,在鼠标右侧展示提示信息
  • Java 使用 poi 和 aspose 实现 word 模板数据写入并转换 pdf 增加水印
  • Spring Boot进阶(93):体验式教程:手把手教你整合Spring Boot和Zipkin
  • Lvs +keepalivede : 高可用集群
  • 得物 Redis 设计与实践yu
  • 优咔科技创新连接方案助力高质量5G车联服务
  • (a /b)*c的值
  • Hive 常用DML操作