Linux中断实操-概念

news2024/9/20 6:22:24

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

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

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

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

2Linux中断API函数

1)中断号

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

2Linux中断申请

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、触发软中断

2tasklet

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、定义中断服务函数、获取中断号,申请中断

7、运行

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");

        

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

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

相关文章

【0~1】实现一个精简版的Tomcat服务器

真正的勇气&#xff0c;是在知道生活的真相之后&#xff0c;依然热爱生活。 《To Kill a Mockingbird》 01 Tomcat 介绍 Tomcat 是一个开源的 Java 应用服务器&#xff0c;主要用来运行基于 Servlet 和 JSP 技术的 Web 应用。Tomcat 实现了 Servlet 规范和 JSP 规范&#xff0…

一次RPC调用过程是怎么样的?

注册中心 RPC&#xff08;Remote Procedure Call&#xff09;翻译成中文就是 {远程过程调用}。RPC 框架起到的作用就是为了实现&#xff0c;调用远程方法时&#xff0c;能够做到和调用本地方法一样&#xff0c;让开发人员更专注于业务开发&#xff0c;不用去考虑网络编程等细节…

【开源免费】基于SpringBoot+Vue.JS企业客户管理系统(JAVA毕业设计)

本文项目编号 T 036 &#xff0c;文末自助获取源码 \color{red}{T036&#xff0c;文末自助获取源码} T036&#xff0c;文末自助获取源码 目录 一、系统介绍1.1 管理员角色1.2 普通员工角色1.3 系统特点 二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内…

苹果手机备份照片怎么删除

在数字时代&#xff0c;备份照片是保护我们珍贵记忆不受意外丢失影响的一种重要方式。苹果手机用户通常利用iCloud或iTunes来备份他们的照片&#xff0c;确保数据的安全。然而&#xff0c;随着时间的推移&#xff0c;这些备份可能会积累大量不再需要的照片&#xff0c;占用宝贵…

鸿蒙开发之ArkTS 基础二

ArkTS常用的基础数据类型 1.字符串 关键字是string 2.数字 关键字是number 3.布尔 关键字是boolean 语法格式是:let 变量名:变量类型 变量值 其中let是关键表示变量&#xff0c;可以修改&#xff0c;可以改变一只对应的是const 修饰&#xff0c;常量不能修改&#xff0c;…

Python画笔案例-050 绘制天空之眼

1、绘制天空之眼 通过 python 的turtle 库绘制 天空之眼&#xff0c;如下图&#xff1a; 2、实现代码 绘制 天空之眼&#xff0c;以下为实现代码&#xff1a; """天空之眼.py """ import math import turtledef draw_square(length,level):if l…

idea同时装了两个版本,每次打开低版本都需要重新激活破解

问题描述&#xff1a; idea同时装了两个版本&#xff0c;每次打开低版本都需要重新激活破解。低版本是2021.1&#xff0c;高版本是2023.1 解决方案&#xff1a; 找到idea的配置路径&#xff0c;比如我的是&#xff1a;C:\Users\Administrator\AppData\Roaming\JetBrains 2021…

【我要成为配环境高手】Nodejs安装与配置

文章目录 1.nodejs安装2.配置npm的全局安装路径3.切换npm的淘宝镜像4.安装vue-cli 1.nodejs安装 从官网下载安装LTS版本的nodejs nodejs会自动安装环境变量&#xff0c;因此安装完成后直接在cmd中查看node版本 node -v2.配置npm的全局安装路径 以管理员身份运行cmd&#xff…

office 2021安装教程

软件介绍 Microsoft Office是微软公司开发的一套基于 Windows 操作系统的办公软件套装。常用组件有 Word、Excel、Powerpoint等。该软件最初出现于九十年代早期&#xff0c;最初是一个推广名称&#xff0c;指一些以前曾单独发售的软件的合集。当时主要的推广重点是购买合集比单…

matlab边缘点提取函数

1、边缘提取 matlab自带点云边缘提取函数,用于搜索点云边界,其核心是alpha shapes算法。alpha shapes提取边缘点,主要是依据滚动圆绕点云进行旋转,实现边缘检测,原理如下图所示。具体原理及效果,可以参考之前我写的博客:基于alpha shapes的边缘点提取(matlab)-CSDN博客…

实习项目|苍穹外卖|day10

Spring Task cron 表达式 入门案例 订单状态定时处理 通知用户支付&#xff01;通知商家完成订单&#xff01; Scheduled(cron "0 0/1 * * * ? ")public void processTimeoutOrder(){log.info("定时处理超时订单: {}", LocalDateTime.now());//答案是…

黑马程序员Java笔记整理(day01)

1.windowsR进入运行&#xff0c;输入cmd 2.环境变量 3.编写java第一步 4.使用idea 5.注释 6.字面量 7.变量 8.二进制 9.数据类型 10.关键词与标识符

仿真软件PROTEUS DESIGN SUITE遇到的一些问题

仿真软件PROTEUS DESIGN SUITE遇到的一些问题 软件网上有很多下载地址自己找哈! 首先如果遇到仿真 没有库 ,需要在网上下载库文件替换到DATA目录下 如果不是默认安装到C盘需要手动修改这些地址,不然会报错!! 当遇到点击仿真出现报错 : 检查这个设置地址是否正确: 随便在库文…

Unity3D 小案例 像素贪吃蛇 02 蛇的觅食

Unity3D 小案例 像素贪吃蛇 第二期 蛇的觅食 像素贪吃蛇 食物生成 在场景中创建一个 2D 正方形&#xff0c;调整颜色&#xff0c;添加 Tag 并修改为 Food。 然后拖拽到 Assets 文件夹中变成预制体。 创建食物管理器 FoodManager.cs&#xff0c;添加单例&#xff0c;可以设置…

周期冲激函数

指数函数的求和----真周期冲击 指数函数有限积分----假单个冲击 指数函数无限积分----真单个冲击

职业院校数据科学与大数据技术专业人工智能实训室建设方案

一、引言 随着人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;其在全球范围内的应用日益广泛&#xff0c;从智能交通、环境保护到公共安全、智能家居等多个领域均展现出巨大的潜力。然而&#xff0c;我国在人工智能领域的人才储备仍显不足&#xff0c;这已成为…

8. 尝试微调LLM大型语言模型,让它会写唐诗

这篇文章与3. 进阶指南&#xff1a;自定义 Prompt 提升大模型解题能力一样&#xff0c;本质上是专注于“用”而非“写”&#xff0c;你可以像之前一样&#xff0c;对整体的流程有了一个了解&#xff0c;尝试调整超参数部分来查看对微调的影响。 这里同样是生成式人工智能导论&a…

华为HarmonyOS地图服务 -- 三种地图类型 -- HarmonyOS9

一. 场景介绍 Map Kit支持以下地图类型&#xff1a; STANDARD&#xff1a;标准地图&#xff0c;展示道路、建筑物以及河流等重要的自然特征。NONE&#xff1a;空地图&#xff0c;没有加载任何数据的地图。TERRAIN&#xff1a;地形图。 1 标准地图&#xff1a; …

7.1溪降技术:徒步

目录 7.1 徒步运动概述观看视频课程电子书&#xff1a;徒步路线选择故事时间不稳定地形 7.1 徒步 运动概述 徒步是溪降活动中不可或缺的一部分&#xff0c;我们在下降峡谷时大部分时间都在徒步。随着我们进入更具挑战性的峡谷&#xff0c;能够高效移动将使我们更加自信和安全。…

Semaphore UI --Ansible webui

1、安装python python下载地址 https://www.python.org/downloads/ 选好版本下载 wget https://www.python.org/ftp/python/3.11.9/Python-3.11.9.tar.xz安装编译工具 sudo dnf groupinstall "Development Tools"安装依赖包 dnf install bzip2-devel ncurses-deve…