阻塞和非阻塞、中断的线程化


一、阻塞和非阻塞

所谓阻塞,就是等待某件事情发生。比如调用 read 读取按键时,如果没有按键数据则 read 函数不会返回,它会让线程休眠等待。
使用 poll 时,如果传入的超时时间不为 0,这种访问方法也是阻塞的。

APP 调用 open 函数时,传入 O_NONBLOCK,就表示要使用非阻塞方式;默认是阻塞方式。
注意:对于普通文件、块设备文件,O_NONBLOCK 不起作用。
注意:对于字符设备文件,O_NONBLOCK 起作用的前提是驱动程序针对 O_NONBLOCK 做了处理。

在 open 之后,也可以通过 fcntl 修改为阻塞或非阻塞。

1、应用层

1、open时设置

int fd = open(/dev/xxx”, O_RDWR | O_NONBLOCK); /* 非阻塞方式 */
int fd = open(/dev/xxx”, O_RDWR ); /* 阻塞方式 */

2、open之后设置

int flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, flags | O_NONBLOCK); /* 非阻塞方式 */
fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); /* 阻塞方式 */

2、驱动层

以drv_read为例:

static ssize_t drv_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK)
	return -EAGAIN;
	wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue));

在内核中会有一个 struct file 结构体对应这个驱动,这个结构体中有 f_flags,就是打开文件时的标记位;可以设置 f_flasgs 的 O_NONBLOCK 位,表示非阻塞;也可以清除这个位表示阻塞。

二、中断的线程化

对于中断处理,还有另一种方法:threaded irq,线程化的中断处理。中断的处理仍然可以认为分为上
半部、下半部。上半部用来处理紧急的事情,下半部用一个内核线程来处理,这个内核线程专用于这个中断。

1、创建线程化中断 request_threaded_irq

int request_threaded_irq(unsigned int irq, 
						irq_handler_t handler,
						irq_handler_t thread_fn, 
						unsigned long irqflags,
						const char *devname,
						 void *dev_id);

thread_fn :创建内核线程去处理的函数

在这里插入图片描述

① 上半部函数如果不提供
内核会提供默认的上半部处理函数:irq_default_primary_handler,它是直接返回 IRQ_WAKE_THREAD。
② 上半部函数如果提供的话:
返回值必须是:IRQ_WAKE_THREAD

在 thread_fn 中,如果中断被正确处理了,应该返回 IRQ_HANDLED。

2、卸载中断 free_irq

void free_irq(unsigned int irq, void *dev_id)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值