Linux的中断上半部和中断下半部的概念,并利用任务队列(Tasklet)实现中断下半部的处理

中断上半部和中断下半部的介绍

在Linux内核中,中断处理机制被设计成“中断上半部(Top Half)”和“中断下半部(Bottom Half)”两个部分,这种设计主要目的是提高系统的中断响应效率,同时减少中断处理对内核其他操作的影响。

中断上半部(Top Half)

  • 概念:中断上半部是指中断发生后,硬件触发的中断处理程序(ISR, Interrupt Service Routine)。

  • 特点

    1. 运行在中断上下文中,不能睡眠。
    2. 优先级高,必须尽快完成,以便处理其他可能的中断。
    3. 通常只完成最必要的工作,例如清除中断源、读取硬件状态等。
    4. 阻塞所有同级或更低优先级的中断。
  • 局限性:由于不能睡眠且运行时间要求短,复杂的工作不能放在上半部。


中断下半部(Bottom Half)

  • 概念中断下半部通常是在中段上半部中指定的任务,当中断上半部完成后,会执行在中断下半部任务,这些任务没有中断上半部那样紧急。它运行在普通进程上下文中,可以执行相对复杂的逻辑。

  • 特点

    1. 在合适的时机由内核调度运行,不会阻塞中断。
    2. 可以睡眠,因为运行在普通的进程上下文中。
    3. 通常处理较为复杂的任务,例如数据处理、通知用户空间等。
  • 实现方式
    Linux 提供了多种机制来实现中断下半部:

    1. 软中断(SoftIRQ)
    2. 任务队列(Tasklet)
      • 通过软中断实现的高级接口,适合较轻量的任务。
      • 也不能睡眠。
    3. 工作队列(Workqueue)
    4. 线程化的中断处理

上半部和下半部的关系

  1. 上半部的任务是快速响应硬件,通知内核某个事件发生,并触发下半部的处理。
  2. 下半部完成真正的处理工作,将中断对内核的影响降到最低。

举例说明

  • 情景:按键中断
    • 上半部:读取硬件寄存器,获取按键的状态,并将事件放入缓冲区,同时触发下半部。
    • 下半部:将按键事件处理为具体的逻辑,比如按键消抖、通知用户空间等。

这种分工明确的设计,使得系统既能快速响应中断,又能在合适的时机完成复杂任务,从而提高整体性能和实时性。

本文代码在哪个基础上修改而成?

本文是在博文 https://blog.csdn.net/wenhao_ir/article/details/145228617 的代码基础上修改而成。

完整源代码

驱动程序gpio_key_drv.c中的代码

#include <linux/module.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>


struct gpio_key{
   
	int gpio;
	struct gpio_desc *gpiod;
	int flag;
	int irq;
	struct tasklet_struct tasklet;
} ;

static struct gpio_key *gpio_keys_100ask;

/* 主设备号                                                                 */
static int major = 0;
static struct class *gpio_key_class;

static int g_key = 0;

static DECLARE_WAIT_QUEUE_HEAD(gpio_key_wait);


/* 环形缓冲区 */
#define BUF_LEN 128
static int g_keys[BUF_LEN];
static int r, w;

#define NEXT_POS(x) ((x+1) % BUF_LEN)

static int is_key_buf_empty(void)
{
   
	return (r == w);
}

static int is_key_buf_full(void)
{
   
	return (r == NEXT_POS(w));
}

static void put_key(int key_value)
{
   
	if (!is_key_buf_full())
	{
   
		g_keys[w] = key_value;
		w = NEXT_POS(w);
	}
}

static int get_key(void)
{
   
	int key_value = 0;
	if (!is_key_buf_empty())
	{
   
		key_value = g_keys[r];
		r = NEXT_POS(r);
	}
	return key_value;
}


/* 实现文件操作结构体中的read函数  */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值