Linux中断

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、中断的相关概念
    • 1.中断号
    • 2.中断的申请和释放
      • 申请API函数如下:
      • 释放API函数如下:
      • 中断处理函数如下:
      • 使能和禁止中断
  • 二、上半部分和下本部分
    • 1.tasklet
    • 2.工作队列
  • 三、设备树中对于中断的描述
  • 三、获取中断号
  • 四、实例如下


前言

使用Linux内核提供的API函数,完成中断的驱动开发。

一、中断的相关概念

1.中断号

中断号的作用是用来区分不同的中断类型,数据结构是int类型。

编写驱动的时候需要用到中断号,我们用到中断号,中断信息已经写到了设备树里面,因
此可以通过 irq_of_parse_and_map 函数从 interupts 属性中提取到对应的设备号,函数原型如下:
unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
函数参数和返回值含义如下:
dev:设备节点。
index:索引号,interrupts 属性可能包含多条中断信息,通过 index 指定要获取的信息。
返回值:中断号。
如果使用 GPIO 的话,可以使用 gpio_to_irq 函数来获取 gpio 对应的中断号,函数原型如下:
int gpio_to_irq(unsigned int gpio)
函数参数和返回值含义如下:
gpio:要获取的 GPIO 编号。
返回值:GPIO 对应的中断号。

2.中断的申请和释放

Linux中使用中断要向内核提交申请,使用完成后要释放掉中断。

申请API函数如下:

int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev)
函数参数和返回值含义如下:
irq:要申请中断的中断号。
handler:中断处理函数,当中断发生以后就会执行此中断处理函数。
flags:中断标志,可以在文件 include/linux/interrupt.h 里面查看所有的中断标志
name:中断名字,设置以后可以在/proc/interrupts 文件中看到对应的中断名字。
dev:如果将 flags 设置为 IRQF_SHARED 的话,dev 用来区分不同的中断,一般情况下将
dev 设置为设备结构体,dev 会传递给中断处理函数 irq_handler_t 的第二个参数。
返回值:0 中断申请成功,其他负值 中断申请失败,如果返回-EBUSY 的话表示中断已经
被申请了

下图提供常用的中断标志
在这里插入图片描述
注意:request_irq函数可能会导致休眠,因此不能在中断上下文或者其他禁止休眠的代码段中使用 request_irq 函数。request_irq 函数会自动激活(使能)中断,所以不需要我们手动去使能中断。

释放API函数如下:

void free_irq(unsigned int irq, void *dev)
函数参数和返回值含义如下:
irq:要释放的中断。
dev:如果中断设置为共享(IRQF_SHARED)的话,此参数用来区分具体的中断。
共享中断只有在释放最后中断处理函数的时候才会被禁止掉。
返回值:无。

注意:如果中断不是共享的,那么 free_irq 会删除中断处理函数并且禁止中断

中断处理函数如下:

irqreturn_t (*irq_handler_t) (int, void *)
第一个参数是要中断处理函数要相应的中断号。第二个参数是一个指向 void 的指针,也就
是个通用指针,需要与 request_irq 函数的 dev 参数保持一致。用于区分共享中断的不同设备,
dev 也可以指向设备数据结构。
中断处理函数的返回值为 irqreturn_t 类型。其定义如下:
10 enum irqreturn {
11 IRQ_NONE = (0 << 0),
12 IRQ_HANDLED = (1 << 0),
13 IRQ_WAKE_THREAD = (1 << 1),
14 };
15
16 typedef enum irqreturn irqreturn_t;
可以看出 irqreturn_t 是个枚举类型,一共有三种返回值
一般中断服务函数返回值使用如下形式:
return IRQ_RETVAL(IRQ_HANDLED)

使能和禁止中断

void enable_irq(unsigned int irq)
void disable_irq(unsigned int irq)

disable_irq函数要等到当前正在执行的中断处理函数执行完才返回,因此使用者需要保证不会产生新的中断,并且确保所有已经开始执行的中断处理程序已经全部退出。那如何处理上述情况的使用如下函数:

void disable_irq_nosync(unsigned int irq)
disable_irq_nosync 函数调用以后立即返回,不会等待当前中断处理程序执行完毕。

上述三个函数是使能或者禁止某一中断,有时候需要使能和关闭整个系统的中断,使用如下函数:

local_irq_enable()
local_irq_disable()

在使用全局中断的时候有个问题,比如当程序A执行关闭10S中断,当2秒后程序B也执行了关闭全局中断,但过了3秒后,B程序又启用了全局中断,但这时候程序A关闭10S还没有结束,这种情况严重会导致系统崩溃。那该怎么解决呢,Linux中提供如下函数解决整个问题

local_irq_save(flags)
local_irq_restore(flags)

这两个函数是成对出现的,local_irq_save 函数用于禁止中断,并且将中断状态保存在 flags 中。local_irq_restore 用于恢复中断,将中断到 flags 状态。

二、上半部分和下本部分

当发生中断的时候,会进入中断处理函数,在函数中,我们希望时间越小越好,但往往事与愿违,在时间驱动编写的时候,在中断处理函数中,需要花费的时间不小,比如电容触摸屏通过中断通知 SOC 有触摸事件发生,SOC 响应中断,然后通过 IIC 接口读取触摸坐标值并将其上报给系统。但是我们都知道 IIC 的速度最高也只有400Kbit/S,所以在中断中通过 IIC 读取数据就会浪费时间。我们可以将通过 IIC 读取触摸数据的操作暂后执行,中断处理函数仅仅响应中断,然后清除中断标志位即可,这种方式就是Linux处理中断的过程:
上半部:上半部就是中断处理函数,那些处理过程比较快,不会占用很长时间的处理就可
以放在上半部完成。
下半部:如果中断处理过程比较耗时,那么就将这些比较耗时的代码提出来,交给下半部
去执行,这样中断处理函数就会快进快出。
比如在上半部将数据拷贝到内存中,关于数据的具体处理就可以放到下半部去执行。至于哪些代码属于上半部,哪些代码属于下半部并没有明确的规定,当然了也是有些经验可以参考的:
①、如果要处理的内容不希望被其他中断打断,那么可以放到上半部。
②、如果要处理的任务对时间敏感,可以放到上半部。
③、如果要处理的任务与硬件有关,可以放到上半部
④、除了上述三点以外的其他任务,优先考虑放到下半部。
那如何将上半部分和下半部分连接起来呢,Linux提供许多方法,可以百度查看一下,下面提供两种常用的方式

1.tasklet

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

484 struct tasklet_struct
485 {
486 struct tasklet_struct *next; /* 下一个 tasklet */
487 unsigned long state; /* tasklet 状态 */
488 atomic_t count; /* 计数器,记录对 tasklet 的引用数 */
489 void (*func)(unsigned long); /* tasklet 执行的函数 */
490 unsigned long data; /* 函数 func 的参数 */
491 };

第 489 行的 func 函数就是 tasklet 要执行的处理函数,用户定义函数内容,相当于中断处理
函数。如果要使用 tasklet,必须先定义一个 tasklet,然后使用 tasklet_init 函数初始化 tasklet,taskled_init 函数原型如下:

void tasklet_init(struct tasklet_struct *t,void (*func)(unsigned long), 
unsigned long data);
函数参数和返回值含义如下:
t:要初始化的 tasklet
func:tasklet 的处理函数。
data:要传递给 func 函数的参数
返回值:没有返回值也可以使用宏 DECLARE_TASKLET 来一次性完成 tasklet 的定义和初始化,
DECLARE_TASKLET 定义在 include/linux/interrupt.h 文件中,定义如下:
DECLARE_TASKLET(name, func, data)
其中 name 为要定义的 tasklet 名字,这个名字就是一个 tasklet_struct 类型的时候变量,func
就是 tasklet 的处理函数,data 是传递给 func 函数的参数。

在上半部,也就是中断处理函数中调用 tasklet_schedule 函数就能使 tasklet 在合适的时间运行,tasklet_schedule 函数原型如下:

void tasklet_schedule(struct tasklet_struct *t)
函数参数和返回值含义如下:
t:要调度的 tasklet,也就是 DECLARE_TASKLET 宏里面的 name。
返回值:没有返回值

使用tasklet的格式如下:

/* 定义 taselet */
struct tasklet_struct testtasklet;
/* tasklet 处理函数 */
void testtasklet_func(unsigned long data)
{/* tasklet 具体处理内容 */
}
/* 中断处理函数 */
irqreturn_t test_handler(int irq, void *dev_id)
{....../* 调度 tasklet */tasklet_schedule(&testtasklet);......
}
/* 驱动入口函数 */
static int __init xxxx_init(void)
{....../* 初始化 tasklet */tasklet_init(&testtasklet, testtasklet_func, data);/* 注册中断处理函数 */request_irq(xxx_irq, test_handler, 0, "xxx", &xxx_dev);......
}

2.工作队列

工作队列是另外一种下半部执行方式,工作队列在进程上下文执行,工作队列将要推后的
工作交给一个内核线程去执行,因为工作队列工作在进程上下文,因此工作队列允许睡眠或重新调度。因此如果你要推后的工作可以睡眠那么就可以选择工作队列,否则的话就只能选择软中断或 tasklet。
简单创建工作很简单,直接定义一个 work_struct 结构体变量即可,然后使用 INIT_WORK 宏来初始化工作,INIT_WORK 宏定义如下:

#define INIT_WORK(_work, _func)
_work 表示要初始化的工作,_func 是工作对应的处理函数。
也可以使用 DECLARE_WORK 宏一次性完成工作的创建和初始化,宏定义如下:
#define DECLARE_WORK(n, f)
n 表示定义的工作(work_struct),f 表示工作对应的处理函数。
和 tasklet 一样,工作也是需要调度才能运行的,工作的调度函数为 schedule_work,函数原
型如下所示:
bool schedule_work(struct work_struct *work)
函数参数和返回值含义如下:
work:要调度的工作。
返回值:0 成功,其他值 失败。

格式如下:

/* 定义工作(work) */
struct work_struct testwork;
/* work 处理函数 */
void testwork_func_t(struct work_struct *work);
{/* work 具体处理内容 */
}
/* 中断处理函数 */
irqreturn_t test_handler(int irq, void *dev_id)
{....../* 调度 work */schedule_work(&testwork);......
}
/* 驱动入口函数 */
static int __init xxxx_init(void)
{....../* 初始化 work */INIT_WORK(&testwork, testwork_func_t);/* 注册中断处理函数 */request_irq(xxx_irq, test_handler, 0, "xxx", &xxx_dev);......
}

三、设备树中对于中断的描述

如果使用设备树的话就需要在设备树中设置好中断属性信息,Linux 内核通过读取设备树中的中断属性信息来配置中断。
在imx6ull中描述中断控制器的节点在imx6ull.dtsi文件中

intc: interrupt-controller@00a01000 {compatible = "arm,cortex-a7-gic";#interrupt-cells = <3>;interrupt-controller;reg = <0x00a01000 0x1000>,<0x00a02000 0x100>;};

compatible 属性值为“arm,cortex-a7-gic”在 Linux 内核源码中搜索“arm,cortex-a7-gic”即可找到中断控制器驱动文件。
#interrupt-cells属性,描述了cells大小,可以在绑定文档中查看其含义:
在这里插入图片描述
第一个 cells:中断类型,0 表示 SPI 中断,1 表示 PPI 中断。
第二个 cells:中断号,对于 SPI 中断来说中断号的范围为 0~987,对于 PPI 中断来说中断
号的范围为 0~15。
第三个 cells:标志,bit[3:0]表示中断触发类型,为 1 的时候表示上升沿触发,为 2 的时候
表示下降沿触发,为 4 的时候表示高电平触发,为 8 的时候表示低电平触发。bit[15:8]为 PPI 中断的 CPU 掩码。
interrupt-controller 节点为空,表示当前节点是中断控制器

对于 gpio 来说,gpio 节点也可以作为中断控制器,比如 imx6ull.dtsi 文件中的 gpio5 节点内
容如下所示:

	gpio5: gpio@020ac000 {compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";reg = <0x020ac000 0x4000>;interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,<GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;gpio-controller;#gpio-cells = <2>;interrupt-controller;#interrupt-cells = <2>;};

interrupts描述中断源信息,属性值大小按照intc中设置填写,对于 gpio5 来说一共有两条信息,中断类型都是 SPI,触发电平都是 IRQ_TYPE_LEVEL_HIGH。不同之处在于中断源,一个是 74,一个是 75,打开可以打开《IMX6ULL 参考手册》的“Chapter 3 Interrupts and DMA Events”章节,找到表 3-1:
在这里插入图片描述
从上图中可以看出,GPIO5 一共用了 2 个中断号,一个是 74,一个是 75。其中 74 对应 GPIO5_IO00-GPIO5_IO15 这低 16 个 IO,75 对应 GPIO5_IO16~GPIOI5_IO31 这高 16 位 IO。
interrupt-controller 表明了 gpio5 节点也是个中断控制器,用于控制 gpio5 所有 IO的中断。
将#interrupt-cells 修改为 2,为什么是2呢,查看绑定信息
在这里插入图片描述
此绑定信息在目录\Documentation\devicetree\bindings\gpio
在这里插入图片描述
上边是NXP官方写的设备树,如果用户要使用该如何使用呢,下面举个例子:

1 fxls8471@1e {
2 compatible = "fsl,fxls8471";
3 reg = <0x1e>;
4 position = <0>;
5 interrupt-parent = <&gpio5>;
6 interrupts = <0 8>;
7 };
fxls8471 是 NXP 官方的 6ULL 开发板上的一个磁力计芯片,fxls8471 有一个中断引脚链接
到了 I.MX6ULL 的 SNVS_TAMPER0 因脚上,这个引脚可以复用为 GPIO5_IO00。
第 5 行,interrupt-parent 属性设置中断控制器,这里使用 gpio5 作为中断控制器。
第 6 行,interrupts 设置中断信息,0 表示 GPIO5_IO00,8 表示低电平触发。
简单总结一下与中断有关的设备树属性信息:
①、#interrupt-cells,指定中断源的信息 cells 个数。
②、interrupt-controller,表示当前节点为中断控制器。
③、interrupts,指定中断号,触发方式等。
④、interrupt-parent,指定父中断,也就是中断控制器

三、获取中断号

编写驱动的时候需要用到中断号,我们用到中断号,中断信息已经写到了设备树里面,因
此可以通过 irq_of_parse_and_map 函数从 interupts 属性中提取到对应的设备号,函数原型如下:

unsigned int irq_of_parse_and_map(struct device_node *dev,int index)
函数参数和返回值含义如下:
dev:设备节点。
index:索引号,interrupts 属性可能包含多条中断信息,通过 index 指定要获取的信息。
返回值:中断号。
如果使用 GPIO 的话,可以使用 gpio_to_irq 函数来获取 gpio 对应的中断号,函数原型如
下:
int gpio_to_irq(unsigned int gpio)
函数参数和返回值含义如下:
gpio:要获取的 GPIO 编号。
返回值:GPIO 对应的中断号。

四、实例如下

#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/export.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>
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/sched.h>
/***************************************************************
Copyright © ALIENTEK Co., Ltd. 1998-2029. All rights reserved.
文件名		: imx6uirq.c
作者	  	: 车文超
版本	   	: V1.0
描述	   	: Linux中断驱动实验
其他	   	: 无
论坛 	   	: 
日志	   	: 
***************************************************************/
#define IMX6ULL_CNT		1			    /* 设备号个数 	*/
#define IMX6ULL_NAME		"imx6ull"	/* 名字 		*/#define KEY0VALUE 0X01 /* KEY0 按键值 */
#define INVAKEY 0XFF /* 无效的按键值 */
#define KEY_NUM 1 /* 按键数量 */
/*按键设备*/
struct key_dev{int gpioid;		            /*gpio编号*/unsigned char value;		/*按键保存值*/char name[10];				/*按键名字*/int irqnum;				/*中断号*/irqreturn_t (*handler)(int, void *); /* 中断服务函数 */
};/* imx6uirq设备结构体 */
struct imx6ull_dev{dev_t devid;			/* 设备号 	 */struct cdev cdev;		/* cdev 	*/struct class *class;	/* 类 		*/struct device *device;	/* 设备 	 */int major;				/* 主设备号	  */int minor;				/* 次设备号   */struct device_node	*nd; /* 设备节点 */struct key_dev key0dev;	/*按键设备*/struct timer_list timerdev;/*定时器设备*/atomic_t keyvalue;/*按键值*/atomic_t release;/*按键释放值*/};struct imx6ull_dev imx6ulldev;	/* imx6ulldev */
/** @description		: 打开设备* @param - inode 	: 传递给驱动的inode* @param - filp 	: 设备文件,file结构体有个叫做private_data的成员变量* 					  一般在open的时候将private_data指向设备结构体。* @return 			: 0 成功;其他 失败*/
static int imx6ull_open(struct inode *inode, struct file *filp)
{filp->private_data = &imx6ulldev;	/* 设置私有数据 */return 0;
}/** @description     : 从设备读取数据 * @param - filp    : 要打开的设备文件(文件描述符)* @param - buf     : 返回给用户空间的数据缓冲区* @param - cnt     : 要读取的数据长度* @param - offt    : 相对于文件首地址的偏移* @return          : 读取的字节数,如果为负值,表示读取失败*/
static ssize_t imx6ull_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{struct imx6ull_dev *dev = (struct imx6ull_dev *)filp->private_data;int ret = 0;int value = 0;int release = 0;value = atomic_read(&dev->keyvalue);release = atomic_read(&dev->release);if(release ==1){if(value & 0x80){value &= ~0x80;ret = copy_to_user(buf,&value,sizeof(value));}else{goto data_error;}atomic_set(&dev->release,0);}else{return -EINVAL;}return ret;
data_error:return -EINVAL;
}/* 设备操作函数 */
static const struct file_operations imx6ull_fops = {.owner = THIS_MODULE,.open = imx6ull_open,.read = imx6ull_read,
};
/** @description	: 中断处理函数* @param 		: 无* @return 		: 无*/
static irqreturn_t key0_irq(int irq, void *dev_id){struct imx6ull_dev *dev = (struct imx6ull_dev *)dev_id;
#if 0value = gpio_get_value(dev->key0dev.gpioid);printk("value=%d\n\r", value);if(value == 0){printk("key0按下");}if(value ==1){printk("key0抬起");}
#endifdev->timerdev.data = (unsigned long)dev_id;mod_timer(&dev->timerdev, jiffies + msecs_to_jiffies(10));return 0;
}
/** @description	: 定时器中断函数* @param 		: 无* @return 		: 无*/
static void timer_func(unsigned long data)
{int value = 0;struct imx6ull_dev *dev = (struct imx6ull_dev *)data;value = gpio_get_value(dev->key0dev.gpioid);printk("value=%d\n\r", value);if(value == 0){printk("key0按下");atomic_set(&dev->keyvalue, dev->key0dev.value);}if(value ==1){printk("key0抬起");atomic_set(&dev->keyvalue, (dev->key0dev.value)|0x80);atomic_set(&dev->release,1);}}/** @description	: 按键初始化函数* @param 		: 无* @return 		: 无*/
static int key_myinit(struct imx6ull_dev *dev_id){int ret = 0	;struct imx6ull_dev *dev = (struct imx6ull_dev *)dev_id;/*1.获取节点*/dev->nd = of_find_node_by_path("/key");if(dev->nd == NULL){printk("of_find_node_by_path_erro\n\r");return -1;}/*2.获取GPIO编号*/dev->key0dev.gpioid = of_get_named_gpio(dev->nd, "key-gpios", 0);if(dev->key0dev.gpioid < 0){printk("of_get_named_gpio_erro\n\r");return -1;}/*3.申请IO*/memset(dev->key0dev.name, 0, sizeof(dev->key0dev.name));//sprintf(dev->keydev[i].name,"KEY%d",i);sprintf(dev->key0dev.name,"key%d",0);ret = gpio_request(dev->key0dev.gpioid,dev->key0dev.name);if(ret < 0){printk("gpio_request_erro\n\r");return -1;}gpio_direction_input(dev->key0dev.gpioid);/*4中断号获取*///dev->keydev[i].irqnum = gpio_to_irq(dev->keydev[i].gpioid);dev->key0dev.irqnum = irq_of_parse_and_map(dev->nd,0);printk("dev->key0dev.irqnum=%d\n\r",dev->key0dev.irqnum);dev->key0dev.handler = key0_irq;dev->key0dev.value = KEY0VALUE;/*5.注册中断*/ret = request_irq(dev->key0dev.irqnum, dev->key0dev.handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,dev->key0dev.name, &imx6ulldev);printk("ret=%d\n\r",ret);if(ret){printk("request_irq_erro\n\r");//goto file_irq;return -1;}/*初始化定时器*/init_timer(&imx6ulldev.timerdev);imx6ulldev.timerdev.function = timer_func;//file_irq:// free_irq(dev->key0dev.irqnum, &imx6ulldev);
return ret;
}
/** @description	: 驱动入口函数* @param 		: 无* @return 		: 无*/
static int __init imx6ull_init(void)
{/* 1、构建设备号 */if (imx6ulldev.major) {imx6ulldev.devid = MKDEV(imx6ulldev.major, 0);register_chrdev_region(imx6ulldev.devid, IMX6ULL_CNT, IMX6ULL_NAME);} else {alloc_chrdev_region(&imx6ulldev.devid, 0, IMX6ULL_CNT, IMX6ULL_NAME);imx6ulldev.major = MAJOR(imx6ulldev.devid);imx6ulldev.minor = MINOR(imx6ulldev.devid);}/* 2、注册字符设备 */cdev_init(&imx6ulldev.cdev, &imx6ull_fops);cdev_add(&imx6ulldev.cdev, imx6ulldev.devid, IMX6ULL_CNT);/* 3、创建类 */imx6ulldev.class = class_create(THIS_MODULE, IMX6ULL_NAME);if (IS_ERR(imx6ulldev.class)) {return PTR_ERR(imx6ulldev.class);}/* 4、创建设备 */imx6ulldev.device = device_create(imx6ulldev.class, NULL, imx6ulldev.devid, NULL, IMX6ULL_NAME);if (IS_ERR(imx6ulldev.device)) {return PTR_ERR(imx6ulldev.device);}/*key初始化*/key_myinit(&imx6ulldev);atomic_set(&imx6ulldev.keyvalue, INVAKEY);atomic_set(&imx6ulldev.release, 0);return 0;
}/** @description	: 驱动出口函数* @param 		: 无* @return 		: 无*/
static void __exit imx6ull_exit(void)
{/*释放中断号,释放IO*/free_irq(imx6ulldev.key0dev.irqnum, &imx6ulldev);gpio_free(imx6ulldev.key0dev.gpioid);/*删除定时器*/del_timer_sync(&imx6ulldev.timerdev);/*删除设备 *//*删除字符设备 */cdev_del(&imx6ulldev.cdev);/*删除设备号 */unregister_chrdev_region(imx6ulldev.devid, IMX6ULL_CNT);/*删除设备 */device_destroy(imx6ulldev.class, imx6ulldev.devid);/*删除类 */class_destroy(imx6ulldev.class);
}module_init(imx6ull_init);
module_exit(imx6ull_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("chewenchao");

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

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

相关文章

基于python实现的深度学习web多格式纠错系统

基于python实现的深度学习web多格式纠错系统 开发语言:Python 数据库&#xff1a;MySQL所用到的知识&#xff1a;Django框架工具&#xff1a;pycharm、Navicat、Maven 系统功能实现 用户登录 登录功能是本系统一个非常重要的功能&#xff0c;这极大的保护了系统的安全。登录…

大模型智力升级:AI的未来之路

大模型的发展引领了人工智能的新时代&#xff0c;其强大的数据处理和学习能力在医疗、金融、教育等众多领域取得了令人瞩目的成就。然而&#xff0c;随之而来的挑战也不容忽视。尽管大模型在特定任务上展现出了卓越的性能&#xff0c;但它们在理解复杂语境、处理未见情况的能力…

【NumPy】全面解析add函数:高效数组加法操作

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

【全开源】Java共享茶室棋牌室无人系统支持微信小程序+微信公众号

打造智能化休闲新体验 一、引言&#xff1a;智能化休闲时代的来临 随着科技的飞速发展&#xff0c;智能化、无人化服务逐渐渗透到我们生活的各个领域。在休闲娱乐行业&#xff0c;共享茶室棋牌室无人系统源码的出现&#xff0c;不仅革新了传统的休闲方式&#xff0c;更为消费…

聊聊最近很火的混合专家模型(MoE)

前段时间&#xff0c;在2024年NVIDIA GTC大会上&#xff0c;英伟达不小心透露了GPT-4采用了MoE架构&#xff0c;模型有1.8万亿参数&#xff0c;由8个220B模型组成&#xff0c;与此前的GPT-4泄露的信息一致。 近半年多以来&#xff0c;各类MoE大模型更是层出不穷。在海外&#…

2024年QMT智能量化交易全解读:一文带你深入了解什么是QMT

随着科技的飞速发展和金融市场的日益成熟&#xff0c;量化交易逐渐成为投资者关注的焦点。QMT&#xff08;Quantitative Market Trading&#xff09;智能量化交易系统&#xff0c;作为量化交易领域的重要工具&#xff0c;以其高效、精准、自动化的特点&#xff0c;受到越来越多…

Ableton Live 11 Suite for Mac:音乐创作的全能伙伴

在数字音乐创作的广阔天地中&#xff0c;Ableton Live 11 Suite for Mac无疑是一颗璀璨的明星。作为一款专业的音乐制作软件&#xff0c;它集合了音频录制、编辑、混音、母带制作等全方位功能&#xff0c;为Mac用户提供了无与伦比的音乐创作体验。 Ableton Live 11 Suite拥有直…

Ubuntu/Linux 安装Paraview

文章目录 0. 卸载已有ParaView1. 安装ParaView1.1 下载后安装 2.进入opt文件夹改名3. 更改启动项4. 创建硬链接5. 添加桌面启动方式6. 即可使用 0. 卸载已有ParaView YUT 1. 安装ParaView https://www.paraview.org/ 1.1 下载后安装 找到下载的文件夹&#xff0c;文件夹内…

NTLM Relay Gat:自动化NTLM中继安全检测工具

关于NTLM Relay Gat NTLM Relay Gat是一款功能强大的NTLM中继威胁检测工具&#xff0c;该工具旨在利用Impacket工具套件中的ntlmrelayx.py脚本在目标环境中实现NTLM中继攻击风险检测&#xff0c;以帮助研究人员确定目标环境是否能够抵御NTLM中继攻击。 功能介绍 1、多线程支持…

AdaBoost 乳腺癌数据挖掘

目录 1.数据集背景 2 集成学习方法 AdaBoost集成过程 3 个体学习器 结果评价 准确率以及混淆矩阵 评估集成学习模型的泛化学习能力 评估集成学习模型的多样性 结论 源码 1.数据集背景 乳腺癌数据集是一个非常经典的二元分类数据集&#xff0c;被广泛应用…

LSTM长短时记忆网络:推导与实现(pytorch)

LSTM长短时记忆网络&#xff1a;推导与实现&#xff08;pytorch&#xff09; 背景推导遗忘门输入门输出门 LSTM的改进&#xff1a;GRU实现 背景 人类不会每秒钟都从头开始思考。当你阅读这篇文章时&#xff0c;你会根据你对以前单词的理解来理解每个单词。你不会把所有东西都扔…

2024年6月1日(星期六)骑行禹都甸

2024年6月1日 (星期六&#xff09;骑行禹都甸&#xff08;韭葱花&#xff09;&#xff0c;早8:30到9:00&#xff0c;昆明氧气厂门口集合&#xff0c;9:30准时出发【因迟到者&#xff0c;骑行速度快者&#xff0c;可自行追赶偶遇。】 偶遇地点:昆明氧气厂门口集合 &#xff0c;…

2024 GIAC 全球互联网架构大会:拓数派向量数据库 PieCloudVector 架构设计与案例实践

5月24-25日&#xff0c;msup 和高可用架构联合举办了第11届 GIAC 全球互联网架构大会。会议聚焦“共话AI技术的最新进展、架构实践和未来趋势”主题&#xff0c;邀请了 100 余位行业内的领军人物和革新者&#xff0c;分享”Agent/RAG 技术、云原生、基座大模型“等多个热门技术…

浏览器修改后端返回值

模拟接口响应和网页内容 通过本地覆盖可以模拟接口返回值和响应头&#xff0c;无需 mock 数据工具&#xff0c;比如&#xff08;Requestly&#xff09;&#xff0c;无需等待后端支持&#xff0c;快速复现在一些数据下的 BUG 等。在 DevTools 可以直接修改你想要的 Fetch/XHR 接…

将四种算法的预测结果绘制在一张图中

​ 声明&#xff1a;文章是从本人公众号中复制而来&#xff0c;因此&#xff0c;想最新最快了解各类智能优化算法及其改进的朋友&#xff0c;可关注我的公众号&#xff1a;强盛机器学习&#xff0c;不定期会有很多免费代码分享~ 之前的一期推文中&#xff0c;我们推出了…

NoSQL是什么?NoSQL数据库存在SQL注入攻击?

一、NoSQL是什么&#xff1f; NoSQL&#xff08;Not Only SQL&#xff09;是一种非关系型数据库的概念。与传统的关系型数据库不同&#xff0c;NoSQL数据库使用不同的数据模型来存储和检索数据。NOSQL数据库通常更适合处理大规模的非结构化和半结构化数据&#xff0c;且能够…

CPU对代码执行效率的优化,CPU的缓存、指令重排序

目录 一、CPU对代码执行效率的优化 1. 指令流水线&#xff08;Instruction Pipelining&#xff09; 2. 超标量架构&#xff08;Superscalar Architecture&#xff09; 3. 动态指令重排序&#xff08;Dynamic Instruction Reordering&#xff09; 4. 分支预测&#xff08;…

【RuoYi】使用代码生成器完成CRUD操作

一、前言 前面&#xff0c;介绍了如何下载和启动我们的RuoYi框架。为了让小伙伴们认识到ruoyi的强大&#xff0c;那么这篇博客就介绍一下如何使用ruoyi的代码生成器&#xff0c;自动生成前端页面以及后端的对应数据库表的CRUD操作&#xff01;&#xff01;&#xff01;真的很强…

LWIP_TCP 协议

目录 1 TCP 协议简介 1.1 TCP 协议简介 1.2 TCP 的建立连接 1.3 TCP 终止连接 1.4 TCP 报文结构 1.5 lwIP 的 TCP 报文首部数据结构 1.6 lwIP 的 TCP 连接状态图 1 TCP 协议简介 1.1 TCP 协议简介 TCP&#xff08;Transmission Control Protocol 传输控制协议&#xff0…

MySQL实战行转列(或称为PIVOT)实战sales的表记录了不同产品在不同月份的销售情况,进行输出

有一个sales的表&#xff0c;它记录了不同产品在不同月份的销售情况&#xff1a; productJanuaryFebruaryMarchProduct AJanuary10Product AFebruary20Product BJanuary5Product BFebruary15Product CJanuary8Product CFebruary12 客户需求展示为如下的样子&#xff1a; pro…