Linux中断-实操、概念

Linux 的中断 文章目录中断概念和分类Linux 中断处理程序架构Linux 中断编程申请和释放中断使能和屏蔽中断底半部机制1. tasklet2.工作队列3.软中断4. threaded irq 中断概念和分类 中断是指 CPU 在执行程序的过程中,出现了某些突发事件急待处理, CPU 必须暂停当前程序的执行,转去处理突发事件,处理完毕后又返回原程序被中断的位置继续执行。 根据中断的来源,中断可分为内部中断和外部中断,内部中断的中断源来自 CPU 内部(软件中断指令、溢出、除法错误等,例如,操作系统从用户态切换到内核态 阅读详情

1、裸机中的中断处理方法:

(1)使能中断、初始化相应寄存器

(2)注册中断服务函数,向irqTable数组的指定标号处写入中断服务函数

(3)中断发生后进入IRQ中断服务函数,执行对应中断处理函数

2、Linux中断API函数

(1)中断号

每个中断都有一个中断号,通过中断号可区分不同中断。

(2)Linux中断申请

Linux内核中想使用一个中断是需要申请的,request_irq函数用于申请中断,request_irq可能会导致睡眠,不能在中断上下文中申请。

参数

  • irq:要申请中断的中断号
  • handler:中断处理函数
  • flags:中断标志位,定义在include/linux/interrupt.h
  • name:中断名字,可在/proc/interrupts中看到
  • dev:若将flags设置为IRQF_SHARED(该中断线被多个设备共享),dev用来区分不同中断,一般情况下,dev设置为设备结构体,dev会传递给handler第二个参数。

Request_irq会激活(使能)中断。

包括上升沿、下降沿等触发方式,可以用|来实现多种组合。

(3)释放中断

free_irq函数。中断完成后要释放掉响应的中断

  • 第一个参数irq:要释放的中断
  • 第二个参数dev:如果中断设置为共享(IRQF_SHARED)的话,此参数用来区分具体的中断。共享中断只有在释放最后中断处理函数时才被禁止。

(4)中断处理函数

  • 第一个参数int:中断处理函数要处理的中断号
  • 第二个参数void*:通用型指针,用于区分共享中断的不同设备,与request_irq函数的dev参数保持一致。

(5)中断使能和禁止函数

关闭指定中断:

  • irq:要禁止的中断号

关闭整个中断系统:

3、上半部与下半部

Linux中中断分为上半部和下半部

上半部:就是中断处理函数,执行速度快的操作放在上半部

下半部:耗时长的放在下半部,以免阻塞系统运行时间过长。

4、下半部的三种实现机制

(1)软中断

(软中断和硬中断相比,就是触发方式不同,由硬件触发变为软件触发,同样会去打断当前进程的执行)

(Linux内核中,软中断被设计为在所有硬件中断处理完后才执行。)

(Linux中硬中断上下文要关中断,无法被其他硬中断打断(禁止中断嵌套)。软中断不关中断,可以被打断。)

  • Linux中使用softirq_action表示软中断

                

  • /kernel/softirq.c文件中一共定义了10软中断

                

                        Softirq_action结构体中的action成员变量就是软中断的服务函数

  • 注册软中断处理函数

                         使用软中断要先注册对应的软中断处理函数,open_softirq

                

                        nr:要开启的软终端

                        action:软中断对应的处理函数

  • 触发软中断

                        软中断注册好后要通过raise_softirq函数触发

                        

                        nr:要触发的软中断

软中断流程:

        a、定义软中断处理函数

        b、注册软中断处理函数

        c、触发软中断

(2)tasklet

tasklet是利用软中断实现的另一种下半部机制。

  • tasklet结构体:

                Linux 内核使用 tasklet_struct 结构体来表示 tasklet                        

                func是tasklet要执行的处理函数,用户定义的函数内容,相当于中断处理函数。使用tasklet前,必须先定义初始化一个tasklet

  • 初始化tasklet

                方式一:

                

        ​​​​​​​        

                        t:要初始化的tasklet

                        func:tasklet的处理函数

                        data:要传递给func函数的参数

                方式二:

        ​​​​​​​        ​​​​​​​        

                        也可以使用宏 DECLARE_TASKLET 来一次性完成 tasklet 的定义和初始化,

                        name:定义的tasklet名字

                        func:tasklet处理函数

                        data:传递给func函数的参数

  • 调用tasklet

                在中断上半部中调用tasklet_schedule函数就能使得tasklet在合适的时间运行

        ​​​​​​​        

                        t:要调度的tasklet

tasklet流程

        a、定义tasklet结构体

        b、定义tasklet处理函数(一个普通的函数)

        c、初始化tasklet

        d、注册中断服务函数

        e、中断服务函数中调度tasklet

(3)工作队列:

另一种下半部执行方式,在进程上下文执行,工作队列将要推后的工作交给一个内核线程执行,工作在进程上下文中

工作

        内核中用work_struct结构体表示一个工作

        

工作队列

        这些工作会组织成一个工作队列,使用workqueue_struct结构体表示

工作线程worker thread

        Linux内核中会使用工作者线程处理工作队列中的各个工作,用worker结构体表示工作者线程。

工作、工作队列、工作线程(工作者)关系

        每个worker都有一个工作队列,工作者线程处理自己工作队列中的所有工作(每个CPU都有个工作者线程,并行处理多个工作)。

        实际开发中,我们只需要定义工作(work_struct)即可,工作队列和工作线程基本不用管。

工作创建

        1)定义一个work_strcut结构体变量

        2)初始化工作

方式一:

#define INIT_WORK(_work, _func)

INIT_WORK宏初始化工作

  • _work:要初始化的工作
  • _func:工作对应的处理函数

方式二:

#define DECLARE_WORK(n, f)

DECLARE_WORK 宏一次性完成工作的创建和初始化

  • n:要定义的工作
  • f:工作对应的处理函数

3)调度工作

需要调用工作才能运行

bool schedule_work(struct work_struct *work)

  • work:要调度的工作
  • 返回值:0 成功,其他值,失败

同样要在中断的上半部,主动开启调度。

(4)threaded irq:(现在的新技术)

单核的时候工作队列只有一个内核线程,还可以,但是如果用到多核,其他核心就浪费了,所以给每个线程都创建一个线程,有专门的线程中断函数,thread_fn中放入线程里要执行的函数。这样子线程平均的分配到多个核心中。

可以只提供 thread_fn,系统会为这个函数创建一个内核线程。发生中断时,内核线程就会执行这个函数。

5、设备树中断信息节点

中断控制器节点

GIC中断控制器节点

  • #interrupt-cells:该中断控制器下设备的cell大小。第一个cell:中断类型,0表示SPI中断,1表示PPI中断。第二个cell:中断号。SPI中断为0~987,PPI中断号为0~15。第三个cell:标志,bit[3:0]表示中断触发类型,为1时表示上升沿触发,为2时表示下降沿触发等。bit[15:8]为PPI中断的CPU掩码
  • interrupt-controller:为空,表示当前节点为中断控制器

GPIO节点中断控制器:gpio5

  • interrupts:描述中断源信息,gpio5一共两条中断源信息,类型都为SPI,触发电平都为IRQ_TYPE_LEVEL_HIGH,不同之处在中断源,一个是74、一个是75

查表可知GPIO5一共用了两个中断号,一个是74、一个是75,分别对应GPIO5_IO00~GPIO5_IO15和GPIO5_IO16~GPIO5_IO31

  • interrupt-controller:表明gpio5节点也是个中断控制器,用于控制所有gpio5所有IO的中断
  • #interrupt-cells:修改为2

Fxls8471是6ULL开发板上的磁力计芯片,有一个中断引脚连接到了SNVS_TAMPER0 引脚上,这个引脚可以复用为 GPIO5_IO00。

  • interrupt-parent 属性:设置中断控制器,使用gpio5作为中断控制器
  • interrupt:设置中断信息,0表示GPIO5_IO00,8表示低电平触发

#interrupt-cells,指定中断源信息的cell个数

interrupt-controller,当前节点为中断控制器

interrupt,指定中断号,触发方式

interrupt-parent,指定父中断,中断控制器

6、设备树里中断

imx6ull.dtsi(厂家提供的)、 100ask_imx6ull-14x14.dts

imx6ull.dtsi:中包含了厂家定义好的中断控制器

100ask_imx6ull-14x14.dts :只需要在外部设备中指定好中断

 

BSP:工程师定义的两个中断控制器(GIC、GPIO等)

(1)GIC中断控制器(厂家):

        1、compatibel:找到对应的驱动程序
        2、interrupt-controller:说明这是一个中断控制器

        3、#interrupt-controller:使用该中断控制器的cell(参数个数)数量

(2)GPIO等中断控制器(厂家):

        1、compatibel:找到对应的驱动程序
        2、interrupt-controller:说明这是一个中断控制器

        3、#interrupt-controller:使用该中断控制器的cell(参数个数)数量

        4、使用上一级哪个中断控制器的哪一个中断

                Interrupt_parent = <& >

                Interrupts = < >  < >  描述一个或多个中断(使用到多个中断时)

(3)指定使用哪一个中断控制器里的哪个中断(我们自己定义)

        1、指定使用哪一个中断控制器里的哪个中断

                Interrupt_parent = <& >

                Interrupts = < >  < >  描述一个或多个中断(使用到多个中断时)

 

GIC中通常Cell有三个属性(下一级中断cell的参数):

1、类(私有中断PPI、还是共享中断SPI)

2、哪个:哪个中断

3、电平触发类型:

要使用 gpio1 里的第 5 号中断, hwirq 就是 5。

7、获取中断号

中断驱动程序编写时要用到中断号,中断信息已写入到设备树中。有两种获取方式。可以用irq_of_parse_and_map函数从interupts属性中提取到对应的设备号

函数参数和返回值含义如下:

  • dev:设备节点
  • index:索引号,interrupt属性中,可能包含多条中断信息,通过index指定要获取的信息

返回值:中断号

若该引脚使用到了GPIO,可以用gpio_to_irq函数获取gpio对应的中断号

  • gpio:要获取的GPIO编号:要获取的GPIO编号

返回值:GPIO对应的中断号

8、按键中断程序过程

a、定义一个软件定时器,完成其初始化,定义其处理函数

b、初始化keyIo,gpio子系统获取设备树信息

c、定义中断服务函数、获取中断号,申请中断

9、运行

cat /proc/interrupts

中断已经成功注册

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/of_irq.h>
#include <linux/irq.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>

#define IMX6UIRQ_CNT		1			/* 设备号个数 	*/
#define IMX6UIRQ_NAME		"imx6uirq"	/* 名字 		*/
#define KEY0VALUE			0X01		/* KEY0按键值 	*/
#define INVAKEY				0XFF		/* 无效的按键值 */
#define KEY_NUM				1			/* 按键数量 	*/

/* 中断IO描述结构体 */
struct irq_keydesc {
	int gpio;								/* gpio */
	int irqnum;								/* 中断号     */
	unsigned char value;					/* 按键对应的键值 */
	char name[10];							/* 名字 */
	irqreturn_t (*handler)(int, void *);	/* 中断服务函数 */
};

/* imx6uirq设备结构体 */
struct imx6uirq_dev{
	dev_t devid;			/* 设备号 	 */
	struct cdev cdev;		/* cdev 	*/
	struct class *class;	/* 类 		*/
	struct device *device;	/* 设备 	 */
	int major;				/* 主设备号	  */
	int minor;				/* 次设备号   */
	struct device_node	*nd; /* 设备节点 */
	atomic_t keyvalue;		/* 有效的按键键值 */
	atomic_t releasekey;	/* 标记是否完成一次完成的按键,包括按下和释放 */
	struct timer_list timer;/* 定义一个定时器*/
	struct irq_keydesc irqkeydesc[KEY_NUM];	/* 按键描述数组 */
	unsigned char curkeynum;				/* 当前的按键号 */
};

struct imx6uirq_dev imx6uirq;	/* irq设备 */

/* @description		: 中断服务函数,开启定时器,延时10ms,
 *				  	  定时器用于按键消抖。
 * @param - irq 	: 中断号 
 * @param - dev_id	: 设备结构。
 * @return 			: 中断执行结果
 */
static irqreturn_t key0_handler(int irq, void *dev_id)
{
	struct imx6uirq_dev *dev = (struct imx6uirq_dev *)dev_id;

	dev->curkeynum = 0;
	dev->timer.data = (volatile long)dev_id;
	mod_timer(&dev->timer, jiffies + msecs_to_jiffies(10));	/* 10ms定时 */
	return IRQ_RETVAL(IRQ_HANDLED);
}

/* @description	: 定时器服务函数,用于按键消抖,定时器到了以后
 *				  再次读取按键值,如果按键还是处于按下状态就表示按键有效。
 * @param - arg	: 设备结构变量
 * @return 		: 无
 */
void timer_function(unsigned long arg)
{
	unsigned char value;
	unsigned char num;
	struct irq_keydesc *keydesc;
	struct imx6uirq_dev *dev = (struct imx6uirq_dev *)arg;

	num = dev->curkeynum;
	keydesc = &dev->irqkeydesc[num];

	value = gpio_get_value(keydesc->gpio); 	/* 读取IO值 */
	if(value == 0){ 						/* 按下按键 */
		atomic_set(&dev->keyvalue, keydesc->value);
	}
	else{ 									/* 按键松开 */
		atomic_set(&dev->keyvalue, 0x80 | keydesc->value);
		atomic_set(&dev->releasekey, 1);	/* 标记松开按键,即完成一次完整的按键过程 */			
	}	
}

/*
 * @description	: 按键IO初始化
 * @param 		: 无
 * @return 		: 无
 */
static int keyio_init(void)
{
	unsigned char i = 0;
	int ret = 0;
	
	imx6uirq.nd = of_find_node_by_path("/key");
	if (imx6uirq.nd== NULL){
		printk("key node not find!\r\n");
		return -EINVAL;
	} 

	/* 提取GPIO */
	for (i = 0; i < KEY_NUM; i++) {
		imx6uirq.irqkeydesc[i].gpio = of_get_named_gpio(imx6uirq.nd ,"key-gpio", i);
		if (imx6uirq.irqkeydesc[i].gpio < 0) {
			printk("can't get key%d\r\n", i);
		}
	}
	
	/* 初始化key所使用的IO,并且设置成中断模式 */
	for (i = 0; i < KEY_NUM; i++) {
		memset(imx6uirq.irqkeydesc[i].name, 0, sizeof(imx6uirq.irqkeydesc[i].name));	/* 缓冲区清零 */
		sprintf(imx6uirq.irqkeydesc[i].name, "KEY%d", i);		/* 组合名字 */
		gpio_request(imx6uirq.irqkeydesc[i].gpio, imx6uirq.irqkeydesc[i].name);
		gpio_direction_input(imx6uirq.irqkeydesc[i].gpio);	
		imx6uirq.irqkeydesc[i].irqnum = irq_of_parse_and_map(imx6uirq.nd, i);
#if 0
		imx6uirq.irqkeydesc[i].irqnum = gpio_to_irq(imx6uirq.irqkeydesc[i].gpio);
#endif
		printk("key%d:gpio=%d, irqnum=%d\r\n",i, imx6uirq.irqkeydesc[i].gpio, 
                                         imx6uirq.irqkeydesc[i].irqnum);
	}
	/* 申请中断 */
	imx6uirq.irqkeydesc[0].handler = key0_handler;
	imx6uirq.irqkeydesc[0].value = KEY0VALUE;
	
	for (i = 0; i < KEY_NUM; i++) {
		ret = request_irq(imx6uirq.irqkeydesc[i].irqnum, imx6uirq.irqkeydesc[i].handler, 
		                 IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, imx6uirq.irqkeydesc[i].name, &imx6uirq);
		if(ret < 0){
			printk("irq %d request failed!\r\n", imx6uirq.irqkeydesc[i].irqnum);
			return -EFAULT;
		}
	}

	/* 创建定时器 */
	init_timer(&imx6uirq.timer);
	imx6uirq.timer.function = timer_function;
	return 0;
}

/*
 * @description		: 打开设备
 * @param - inode 	: 传递给驱动的inode
 * @param - filp 	: 设备文件,file结构体有个叫做private_data的成员变量
 * 					  一般在open的时候将private_data指向设备结构体。
 * @return 			: 0 成功;其他 失败
 */
static int imx6uirq_open(struct inode *inode, struct file *filp)
{
	filp->private_data = &imx6uirq;	/* 设置私有数据 */
	return 0;
}

 /*
  * @description     : 从设备读取数据 
  * @param - filp    : 要打开的设备文件(文件描述符)
  * @param - buf     : 返回给用户空间的数据缓冲区
  * @param - cnt     : 要读取的数据长度
  * @param - offt    : 相对于文件首地址的偏移
  * @return          : 读取的字节数,如果为负值,表示读取失败
  */
static ssize_t imx6uirq_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
	int ret = 0;
	unsigned char keyvalue = 0;
	unsigned char releasekey = 0;
	struct imx6uirq_dev *dev = (struct imx6uirq_dev *)filp->private_data;

	keyvalue = atomic_read(&dev->keyvalue);
	releasekey = atomic_read(&dev->releasekey);

	if (releasekey) { /* 有按键按下 */	
		if (keyvalue & 0x80) {
			keyvalue &= ~0x80;
			ret = copy_to_user(buf, &keyvalue, sizeof(keyvalue));
		} else {
			goto data_error;
		}
		atomic_set(&dev->releasekey, 0);/* 按下标志清零 */
	} else {
		goto data_error;
	}
	return 0;
	
data_error:
	return -EINVAL;
}

/* 设备操作函数 */
static struct file_operations imx6uirq_fops = {
	.owner = THIS_MODULE,
	.open = imx6uirq_open,
	.read = imx6uirq_read,
};

/*
 * @description	: 驱动入口函数
 * @param 		: 无
 * @return 		: 无
 */
static int __init imx6uirq_init(void)
{
	/* 1、构建设备号 */
	if (imx6uirq.major) {
		imx6uirq.devid = MKDEV(imx6uirq.major, 0);
		register_chrdev_region(imx6uirq.devid, IMX6UIRQ_CNT, IMX6UIRQ_NAME);
	} else {
		alloc_chrdev_region(&imx6uirq.devid, 0, IMX6UIRQ_CNT, IMX6UIRQ_NAME);
		imx6uirq.major = MAJOR(imx6uirq.devid);
		imx6uirq.minor = MINOR(imx6uirq.devid);
	}

	/* 2、注册字符设备 */
	cdev_init(&imx6uirq.cdev, &imx6uirq_fops);
	cdev_add(&imx6uirq.cdev, imx6uirq.devid, IMX6UIRQ_CNT);

	/* 3、创建类 */
	imx6uirq.class = class_create(THIS_MODULE, IMX6UIRQ_NAME);
	if (IS_ERR(imx6uirq.class)) {
		return PTR_ERR(imx6uirq.class);
	}

	/* 4、创建设备 */
	imx6uirq.device = device_create(imx6uirq.class, NULL, imx6uirq.devid, NULL, IMX6UIRQ_NAME);
	if (IS_ERR(imx6uirq.device)) {
		return PTR_ERR(imx6uirq.device);
	}
	
	/* 5、初始化按键 */
	atomic_set(&imx6uirq.keyvalue, INVAKEY);
	atomic_set(&imx6uirq.releasekey, 0);
	keyio_init();
	return 0;
}

/*
 * @description	: 驱动出口函数
 * @param 		: 无
 * @return 		: 无
 */
static void __exit imx6uirq_exit(void)
{
	unsigned int i = 0;
	/* 删除定时器 */
	del_timer_sync(&imx6uirq.timer);	/* 删除定时器 */
		
	/* 释放中断 */
	for (i = 0; i < KEY_NUM; i++) {
		free_irq(imx6uirq.irqkeydesc[i].irqnum, &imx6uirq);
		gpio_free(imx6uirq.irqkeydesc[i].gpio);
	}
	cdev_del(&imx6uirq.cdev);
	unregister_chrdev_region(imx6uirq.devid, IMX6UIRQ_CNT);
	device_destroy(imx6uirq.class, imx6uirq.devid);
	class_destroy(imx6uirq.class);
}

module_init(imx6uirq_init);
module_exit(imx6uirq_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zuozhongkai");

        

linux的中断使用 Linux的中断使用,中断的上半部和下半部的介绍,以及实现中断下半部的方法,和各种中断控制的API 阅读详情

相关推荐

Linux中断 -- 中断路由、优先级、数据和标识

承前文,本文从中断路由、优先级、数据结构和标识意义等方面对Linux内核中断进行一步的解析。

hello_yj的专栏 2782

嵌入式Linux开发26——Linux 中断(万字总结)

文章目录Linux中断简介:1. Linux 中断 API 函数1.1 中断号1.2 request_irq 函数1.3 free_irq 函数1.4 中断处理函数1.5 中断使能与禁止函数2.上半部与下半部2.1 软中断   不管是裸机实验还是 Linux 下的驱动实验,中断都是频繁使用的功能,在裸机中使用中断我们需要做一大堆的工作,比如配置寄存器,使能 IRQ 等等。 Linux 内核提供了完善的中断框架,我们只需要申请中断,然后注册中断处理函数即可,使用非常方便,不需要一系列复杂的寄存器配置。 Li

贾贾的博客 8633

Linux内核基础——Linux中断的概念

一、什么是中断? 中断是指计算机运行过程中,出现某些意外情况需要主机干预时,中断源向CPU发送一个中断请求,CPU能进行中断响应去停止正在运行的程序并且保护现场数据,然后转入中断服务程序进行处理,处理完毕后又返回原来被暂停的程序继续运行。 二、Intel对中断的分类 1、同步中断(异常) CPU在执行程序的某条指令时,发生了异常错误,由cpu产生的中断,这种错误一般由程序的书写错误产生(内存越...

SuperBoy_Zjc 1013

Linux中断

Interrupt Request,简称IRQ,中断是指在CPU正常运行期间,由于内外部事件或由程序预先安排的事件引起的 CPU 暂时停止正在运行的程序,转而为该内部或外部事件或预先安排的事件服务的程序中去,服务完毕后再返回去继续运行被暂时中断的程序。软件对硬件进行配置后,软件期望等待硬件的某种状态(比如,收到了数据,GPIO状态变化),这里有两种方式,一种是轮询(polling): CPU 不断的去读硬件状态。

tiandiyixian20的博客 2525

RK3308B开发板WiFi+蓝牙一体模组RTL8821CS驱动移植保姆级教程(含DTS配置与避坑点)

本文提供RK3308B开发板RTL8821CS WiFi+蓝牙模组驱动移植的完整教程,涵盖SDK环境配置、DTS设备树设置、内核编译优化及功能验证全流程。重点解析引脚复用冲突、电源管理等关键配置,并给出常见错误解决方案,帮助开发者快速实现双模通信功能。

weixin_42531163的博客 398

Oracle 11g版本下载及安装超详细教程图解

新手Oracle安装教程

weixin_43738344的博客 10万+

linux中断介绍(概念、顶半部和底半部、linux中断编程)

中断的概念: 指CPU在执行过程中,出现某些突发事件急待处理,CPU暂停执行当前程序,转去处理突发事件,处理完后CPU又返回原程序被中断的位置继续执行. 中断的分类: 内部中断:来自cpu内部(软件中断、cpu溢出、触发错误等) 外部中断:来自cpu外部,由外设触发 屏蔽中断和不可屏蔽中断 可屏蔽中断:可以通过屏蔽字被屏蔽,屏蔽后该中断不再触发响应 不可屏蔽中断:中断无法...

夏天Alex 2885

视频动作识别、行为识别、时空动作检测数据集整理(持续更新)

动作、行为、事件 在计算机视觉的相关研究中,人体的动作、行为识别是一个基础研究问题。但目前识别、检测人类的动作/行为仍然是一个巨大的挑战。这里整理下当前相关的细分任务、数据集和开源代码(持续更新中)。

人工智能算法与工程实践 3万+

【系列文章】Linux系统中断的应用01-Linux内核中的中断概念

中断是指在 CPU 正常运行期间,由外部或内部事件引起的一种机制。当中断发生时,CPU会停止当前正在执行的程序,并转而执行触发该中断的中断处理程序。处理完中断处理程序后,CPU 会返回到中断发生的地方,继续执行被中断的程序。中断机制允许 CPU 在实时响应外部或内部事件的同时,保持对其他任务的处理能力。

qq_56861680的博客 1079

Kali Linux实战:5分钟复现永恒之蓝漏洞攻击(附Win7靶机配置指南)

本文提供了一份详细的Kali Linux实战指南,指导读者在5分钟内于隔离的虚拟环境中复现经典的永恒之蓝漏洞攻击。内容涵盖从Windows 7靶机配置、网络设置,到使用Nmap进行服务发现、利用Metasploit框架进行漏洞扫描与利用的全过程,并演示了基础的Meterpreter后渗透操作,旨在帮助网络安全学习者通过亲手实践深入理解SMB协议漏洞的攻防原理。

weixin_29313547的博客 196

如何给K8S配置一个具有永久有效的kubeconfig

在 Amazon EKS 环境中,Kubernetes 的认证机制与 AWS IAM 深度集成,通过aws-iam-authenticator动态生成临时凭证。这种设计虽然增强了安全性,但给需要持久化凭证的工具链(如 CI/CD 系统中的 KubeVela)带来了挑战。具体表现为:临时凭证失效​​:默认 Token 有效期为 15 分钟至 1 小时;​​IAM 角色限制​​:直接使用aws eks get-token生成的凭证无法持久化

小杨同学的博客 660

中断基础概念 与 Linux底半部实现机制总结

内部中断/外部中断:内部中断源来自于CPU内部,如溢出、软件中断指令 等;外部中断来自于CPU外部,由外设提出中断请求可屏蔽中断/不可屏蔽中断:可屏蔽中断可以通过配置中断控制寄存器等方法被屏蔽,屏蔽后不再处理响应中断向量中断/非向量中断:向量中断会给中断分配中断号,由硬件决定中断入口地址;非向量中断共享同一个入口地址,进入该地址后,再由软件判别具体执行哪个中断处理函数,下面是非向量中断的中断服务程序示例。

weixin_44178960的博客 1354

ubuntu 20.04 搭建多用户远程桌面共享及同时在线使用

摘要:本文介绍了在物理机上配置远程桌面访问的完整流程。通过setup_xrdp.sh脚本自动安装xrdp服务,修改配置文件并开放3389端口。同时提供了用户管理脚本:add_rdp_users.sh用于创建带sudo权限的远程用户,del_rdp_users.sh用于删除用户及主目录。还包含批量操作脚本add_rdp_all.sh和del_rdp_all.sh,支持一次性创建/删除多个用户(如dev1-dev5),所有用户密码统一设置为111111。完整方案实现了远程桌面环境的快速部署和用户集中管理。

623

20240309 一文了解Linux内核中断基本概念

Linux驱动中,中断是频繁使用的功能,Linux内核为我们提供了完整的中断框架,我们只需要申请中断,注册中断处理函数即可。

awildchild1的博客 1104

YOLO26魔改神技:YOLO26引入SimAM(无参注意力):不增加网络参数的3D能量函数提点黑科技

文章摘要 2026年YOLO26模型发布引发边缘计算革命,但特定场景精度不足问题催生注意力机制改进需求。本文聚焦无参数注意力机制SimAM,基于神经科学理论通过3D能量函数直接计算神经元权重,实现零参数量提升模型性能。文章深度解析YOLO26四大创新架构,对比SimAM与传统注意力机制差异,并探讨其在YOLO26中的集成方案。研究显示,SimAM在不增加模型体积前提下显著提升mAP指标,特别适合边缘端部署。全文涵盖架构设计、代码实现、竞品对比、部署方案等维度,为轻量化视觉模型优化提供系统解决方案。

ZDQ58818的博客 273

R数据分析:广义估计方程式GEE的做法和解释

好久没有更新文章了,因为同学们咨询的问题有点多,另一个原因就是自己实在太懒。。。。 今天继续给大家写广义估计方程式GEE。 In statistics, a generalized estimating equation (GEE) is used to estimate the parameters of a generalized linear model with a possible unknown correlation between outcomes. 上面的英文解释告诉我们,当我们

Codewar的博客 1万+

详解 Linux 系统中断概念和处理过程

硬中断是由外部硬件设备触发的信号。它是设备向CPU发送的一种请求,以告知CPU该设备需要处理的事件或状态变化。硬中断通常由外部设备(如键盘、鼠标、网络接口卡、磁盘驱动器等)通过中断请求线(IRQ)向CPU发送信号。当设备完成数据传输、发生错误或状态变化时会产生硬中断。以下为硬中断的特点:异步: 硬中断是异步事件,不受当前正在执行的程序控制。快速响应: 硬中断通常会被立即处理,以确保及时响应设备的请求。优先级: 硬中断可以设置优先级,以便高优先级的中断可以中断低优先级的中断处理。软中断。

weixin_46919680的博客 1160

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Linux 中断概念和分析

打开Linux源码/include/linux/interrupt.h,下面是软中断号,enum {*/TEST_SOFTIRQ, //添加的自定义软中断//要在前面之前,最后一个是总的数字和一些API/*初始化nr:软中断的编号action:指向一个函数的指针*//*触发软中断nr: 软中断的编号或优先级。*//*关闭软中断nr: 软中断的编号或优先级。*///// 软中断处理程序//触发软中断。

2202_75321950的博客 406

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Linux驱动之中断

tasklet 用法同中断基本实验的注意点tasklet 基本的api 注册、使能、调度、停止使能、消除tasklet 用法,就是在中断注册服务中让tasklet 调度。task 调度之前必须先注册并开启使能调度方法执行后,执行的就是tasklet 注册时候关联的tasklet回调方法软中断 用法同中断基本实验的注意点1)软中断 基本的api 注册、触发2)软中断 用法,就是在中断注册服务中让软中断触发。3)软中断 触发之前必须先注册。

十年饮冰,难凉热血 1026

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Linux中断解析

Linux中断解析摘要:本章将向读者依次解释中断概念,解析Linux中的中断实现机理以及Linux下中断如何被使用。作为实例我们第一将向《i386体系结构》一章中打造的系统加入一个时钟中断;第二将为大家注解RTC中断,希望通过这两个实例可以帮助读者掌握中断相关的概念、实现和编程方法。中断是什么中断的汉语解释是半中间发生阻隔、停顿或故障而断开。那么,在计算机系统中,我们为什么需要“阻

康华的专栏 8981

Linux中断及其处理

Linux中断处理机制摘要 Linux中断处理机制分为上半部和下半部。上半部在屏蔽中断状态下快速处理紧急任务(如硬件应答),下半部通过软中断、tasklet或工作队列延迟处理耗时操作。软中断和tasklet基于优先级执行,而工作队列则允许睡眠和阻塞,适用于复杂任务。线程化中断将部分处理移至内核线程,减少中断延迟。内核提供request_irq()注册中断处理函数,并通过中断向量表管理不同中断源。这种分层设计平衡了实时响应与系统效率,是操作系统与硬件交互的核心机制。

weixin_43192805的博客 957

Linux中断基础概念

Linux中断基础概念 回顾 裸机开发 通用中断控制器(GIC) 中断类型、硬件中断号、分发器和cpu接口单元 中断向量表 一级查表、二级查表 中断处理流程 进入irq模式、保护现场、获取硬件中断编号、执行中断处理函数、还原现场 GIC中断控制器节点 arch/arm/boot/dts/imx6ull.dtsi 初始化中断控制器、设置其他中断控制器节点的描述格式 intc: interrupt-controller@a01000 { compatible = "arm,cor

十七阿哥的博客 488

linux基本概念之中断、轮询

用通俗易懂的语言来阐述一些基本概念,不涉及代码,小白也能看得懂。 中断是什么 意思就是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。 中断是一种计算机术语。通俗点说就是停下当前的执行程序转而执行新的程序。 执行完后再返回执行之前的程序。 为什么要有中断 因为外围设备和CPU处理速度不对等。就好比电脑的处理速度和你键盘打字的输入速度,电脑处理速度非常快,如果一直等待你输入,那样非常浪费资源。 更通俗的说,老板说明

aw的博客 1800
上一篇: 【操作系统】基础知识总结、深入理解
下一篇: Linux中断、软中断、MMU内存映射-深入理解
ZHU~.
博客等级 码龄7年 193粉丝 24原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值