【LV15 DAY7 阻塞和非阻塞】

news2025/6/21 4:00:07

一、五种IO模型------读写外设数据的方式

阻塞: 不能操作就睡觉

在这里插入图片描述
非阻塞:不能操作就返回错误

在这里插入图片描述

多路复用:委托中介监控



信号驱动:让内核如果能操作时发信号,在信号处理函数中操作



异步IO:向内核注册操作请求,内核完成操作后发通知信号

二、阻塞与非阻塞

应用层:

​ open时由O_NONBLOCK指示read、write时是否阻塞

​ open以后可以由fcntl函数来改变是否阻塞:

flags = fcntl(fd,F_GETFL,0);
flags |= O_NONBLOCK;
fcntl(fd, F_SETFL, flags);

驱动层:通过等待队列

wait_queue_head_t //等待队列头数据类型

init_waitqueue_head(wait_queue_head_t *pwq) //初始化等待队列头

wait_event_interruptible(wq,condition)
/*
功能:条件不成立则让任务进入浅度睡眠,直到条件成立醒来
wq:等待队列头
condition:C语言表达式
返回:正常唤醒返回0,信号唤醒返回非0(此时读写操作函数应返回-ERESTARTSYS)
*/

wait_event(wq,condition) //深度睡眠

wake_up_interruptible(wait_queue_head_t *pwq)

wake_up(wait_queue_head_t *pwq)

/*

  1. 读、写用不同的等待队列头rq、wq
  2. 无数据可读、可写时调用wait_event_interruptible(rq、wq,条件)
  3. 写入数据成功时唤醒rq,读出数据成功唤醒wq
    */

代码实现:

ssize_t mychar_read(struct file *pfile,char __user *puser,size_t count,loff_t *p_pos)
{
	struct mychar_dev *pmydev = (struct mychar_dev *)pfile->private_data;
	int size = 0;
	int ret = 0;

	if(pmydev->curlen <= 0)
	{
		if(pfile->f_flags & O_NONBLOCK)
		{//非阻塞
			printk("O_NONBLOCK No Data Read\n");
			return -1;
		}
		else
		{//阻塞
			ret = wait_event_interruptible(pmydev->rq,pmydev->curlen > 0);
			if(ret)
			{
				printk("Wake up by signal\n");
				return -ERESTARTSYS;
			}
		}
	}

	if(count > pmydev->curlen)
	{
		size = pmydev->curlen;
	}
	else
	{
		size = count;
	}

	ret = copy_to_user(puser,pmydev->mydev_buf,size);
	if(ret)
	{
		printk("copy_to_user failed\n");
		return -1;
	}

	memcpy(pmydev->mydev_buf,pmydev->mydev_buf + size,pmydev->curlen - size);

	pmydev->curlen -= size;

	wake_up_interruptible(&pmydev->wq);
		
	return size;
}

ssize_t mychar_write(struct file *pfile,const char __user *puser,size_t count,loff_t *p_pos)
{
	int size = 0;
	int ret = 0;
	struct mychar_dev *pmydev = (struct mychar_dev *)pfile->private_data;

	if(pmydev->curlen >= BUF_LEN)
	{
		if(pfile->f_flags & O_NONBLOCK)
		{
			printk("O_NONBLOCK Can not write data\n");
			return -1;
		}
		else
		{
			ret = wait_event_interruptible(pmydev->wq,pmydev->curlen < BUF_LEN);
			if(ret)
			{
				printk("wake up by signal\n");
				return -ERESTARTSYS;
			}
		}
	}


	if(count > BUF_LEN-pmydev->curlen)
	{
		size = BUF_LEN - pmydev->curlen;
	}
	else
	{
		size = count;
	}

	ret = copy_from_user(pmydev->mydev_buf + pmydev->curlen,puser,size);
	if(ret)
	{
		printk("copy_from_user failed\n");
		return -1;
	}
	pmydev->curlen  +=  size;

	wake_up_interruptible(&pmydev->rq);

	return size;
}

int __init mychar_init(void)
{
	int ret = 0;
	dev_t devno = MKDEV(major,minor);
	int i = 0;

	/*申请设备号*/
	ret = register_chrdev_region(devno,mychar_num,"mychar");
	if(ret)
	{
		ret = alloc_chrdev_region(&devno,minor,mychar_num,"mychar");
		if(ret)
		{
			printk("get devno failed\n");
			return -1;
		}
		major = MAJOR(devno);//容易遗漏,注意
	}


		/*给struct cdev对象指定操作函数集*/	
		cdev_init(&gmydev.mydev,&myops);

		/*将struct cdev对象添加到内核对应的数据结构里*/
		gmydev.mydev.owner = THIS_MODULE;
		cdev_add(&gmydev.mydev,devno,1);
		
	//初始化等待队列//
	init_waitqueue_head(&gmydev.rq);
	init_waitqueue_head(&gmydev.wq);

	return 0;
}

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

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

相关文章

Web本体语言OWL

语义网&#xff08;Semantic Web&#xff09;&#xff1a; 语义网是万维网联盟&#xff08;W3C&#xff09;提出的一种愿景&#xff0c;旨在增强现有Web的表达能力和智能处理能力&#xff0c;通过标准化的技术手段赋予网络数据更加精确和可计算的语义&#xff0c;使得机器能够…

Ubuntu18/20运行ORB-SLAM3

ORB-SLAM3复现(ubuntu18/20) 文章目录 ORB-SLAM3复现(ubuntu18/20)1 坐标系与外参Intrinsic parameters2 内参Intrinsic parameters2.1 相机内参① 针孔模型Pinhole② KannalaBrandt8模型③ Rectified相机 2.2 IMU内参 3 VI标定—外参3.1 Visual calibration3.2 Inertial calib…

【Appium问题】每次启动appium都会安装一次uiautomator

问题 每次启动appium&#xff0c;都需要安装一次uiautomator2比较麻烦 解决 在配置文件capabilities 中增加参数skipServerInstallationTrue

CSDN,最全API接口测试入门教程到实战

由于自己想学习API方面的测试&#xff0c;但是市面上搜不到相关的图书可以系统学习&#xff0c;网上的内容又零零散散&#xff0c;适合有点API开发基础的人去搜索。为了方面新手学习API测试&#xff0c;现在整理了他人的宝贵经验和自己的学习心得&#xff0c;尽量在一篇文章中囊…

git删除comimit提交的记录

文章目录 本地的删除远程同步修改上次提交更多详情阅读 本地的删除 例如我的提交历史如下 commit 58211e7a5da5e74171e90d8b90b2f00881a48d3a Author: test <test36nu.com> Date: Fri Sep 22 20:55:38 2017 0800add d.txtcommit 0fb295fe0e0276f0c81df61c4fd853b7a00…

【开源】JAVA+Vue.js实现食品生产管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 加工厂管理模块2.2 客户管理模块2.3 食品管理模块2.4 生产销售订单管理模块2.5 系统管理模块2.6 其他管理模块 三、系统展示四、核心代码4.1 查询食品4.2 查询加工厂4.3 新增生产订单4.4 新增销售订单4.5 查询客户 五、…

水果音乐编曲软件 FL Studio v21.2.3.4004 中文免费版(附中文设置教程)以及新功能介绍

FL studio21中文别名水果编曲软件&#xff0c;是一款全能的音乐制作软件&#xff0c;包括编曲、录音、剪辑和混音等诸多功能&#xff0c;让你的电脑编程一个全能的录音室&#xff0c;它为您提供了一个集成的开发环境&#xff0c;使用起来非常简单有效&#xff0c;您的工作会变得…

Linux编程3.6 进程-其他进程及函数

1、僵尸进程 子进程结束但是没有完全释放内存&#xff08;在内核中的task_struct没有释放&#xff09;&#xff0c;该进程就成为僵尸进程。当僵尸进程的父进程结束后就会被init进程领养&#xff0c;最终被回收。避免僵尸进程 让僵尸进程的父进程来回收&#xff0c;父进程每隔一…

StringBuffer与StringBuilder的常用方法及源码分析。

StringBuffer与StringBuilder的常用方法及源码分析 1. 常用方法2. 源码分析 StringBuffer和StringBuilder都是用于处理字符串的可变对象&#xff0c;它们之间的主要区别在于StringBuffer是线程安全的&#xff0c;而StringBuilder是非线程安全的。 1. 常用方法 append()&#…

使用jar命令删除.jar文件中的重复的类和目录并重新打包

引言&#xff1a; android项目&#xff0c;引入的 .jar包 和 .aar中 有相同的类&#xff0c;导致编译冲突&#xff0c;由于这些依赖项没有上传到Maven仓库&#xff0c;无法使用 exclude 排除&#xff0c;只能尝试修改jar文件&#xff0c;删除重复的代码&#xff0c;再重新打包…

【深度学习笔记】6_8 长短期记忆(LSTM)

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;部分标注了个人理解&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 6.8 长短期记忆&#xff08;LSTM&#xff09; 本节将介绍另一种常用的门控循环神经网络&#xff1a;长短期记忆&#xff08;long shor…

qt自绘标尺,鼠标拖动画线测量两点距离

效果如图&#xff1a; 图像显示窗口元素组成&#xff1a; 图像显示窗口整体构成&#xff1a; 长度测量窗口ui&#xff1a; 思路&#xff1a; 首先自定了一个RulerWidget&#xff0c;其中有一个布局&#xff0c;布局中包含自定义的水平Ruler、自定义垂直Ruler、单位QLab…

洗地机怎么选|洗地机哪款好用?添可、希亦、美的洗地机哪个最耐用质量好?

在现代生活中&#xff0c;屋内清洁是一项必不可少的工作&#xff0c;但也是一项费时费力的工作。随着科技的进步&#xff0c;家庭清洁工具也正经历着革命性的变革。洗地机&#xff0c;一种集吸尘、拖地、清洗于一体的智能家居清洁工具&#xff0c;正逐渐成为现代家庭必备的家电…

15. 三数之和 - 力扣

1. 题目 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组。 …

华容道问题求解_详细设计(四)之查找算法2_BFS

&#xff08;续上篇&#xff09; 利用BFS查找&#xff0c;会找到最短路径&#xff08;没有权重的图&#xff09;&#xff0c;这个道理比较简单&#xff0c;这是由于寻找路径的方法都是从起点或者接近起点的位置开始的。查找过程如果画出图来&#xff0c;类似于一圈圈的放大&…

C++初阶:类与对象(中篇)

目录 2. 类的六个默认成员函数2.1 构造函数2.1.1 构造函数的定义方式 2.2 析构函数2.2.1 析构函数定义方式 2.3拷贝构造函数2.3.1 拷贝构造函数的定义方式2.3.2 深拷贝与浅拷贝 2.4 赋值运算符的重载2.4.1 运算符重载2.4.2 运算符的重载的定义方式2.4.3 默认成员函数&#xff1…

Redis 常见数据类型(对象类型)和应用案列

前言: 每次你在游戏中看到玩家排行榜&#xff0c;或者在音乐应用中浏览热门歌单&#xff0c;有没有想过这个排行榜是如何做到实时更新的&#xff1f;当然&#xff0c;依靠 Redis 即可做到。 在技术领域&#xff0c;我们经常听到「键值存储」 这个词。但在 Redis 的世界里&…

VBA技术资料MF128:批量创建文件夹及子文件夹

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

低密度奇偶校验码LDPC(十)——LDPC码的密度进化

一、密度进化的概念 二、规则LDPC码的密度进化算法(SPA算法) 算法变量表 VN更新的密度进化 CN更新的密度进化 算法总结 程序仿真 参考文献 [1] 白宝明 孙韶辉 王加庆. 5G 移动通信中的信道编码[M]. 北京: 电子工业出版社, 2018. [2] William E. Ryan, Shu Lin. Channel Co…

【C语言】linux内核ip_local_out函数

一、讲解 这个函数 __ip_local_out 是 Linux 内核网络子系统中的函数&#xff0c;部分与本地出口的 IPv4 数据包发送相关。下面讲解这段代码的每一部分&#xff1a; 1. 函数声明 int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)&#xff1a; -…