当前位置: 首页 > news >正文

Linux 中断实验

目录

一、Linux 中断简介

上半部与下半部

二、添加设备树

三、编写驱动

1、定义宏

 2、编写一个key结构体

3、imx6uirq设备添加成员 

​编辑4、按键中断处理函数

5、按键初始化

6、在驱动入口添加初始化

7、 驱动出口函数

 代码如下

四、利用定时器进行消抖处理

1、添加定时器

 2、修改中断处理函数

3、添加定时器处理函数

4、在按键初始化函数最后添加初始化定时器

 5、驱动出口函数添加删除定时器

五、编写测试app

1、添加原子操作

2、初始化原子变量

3、按下和释放操作

4、读函数操作

总体代码如下


一、Linux 中断简介

在 Linux 内核中要想使用某个中断是需要申请的,使用完成以后就要释放掉相应的中断,申请中断的时候需要设置中断处理函数,还有设置使能中断与禁止

上半部与下半部

有些资料中也将上半部和下半部称为顶半部和底半部。

上半部:上半部就是中断处理函数,那些处理过程比较快,不会占用很长时间的处理就可以放在上半部完成。
下半部:如果中断处理过程比较耗时,那么就将这些比较耗时的代码提出来,交给下半部去执行,这样中断处理函数就会快进快出。
至于哪些代码属于上半部,哪些代码属于下半部并没有明确的规定,如果要处理的内容不希望被其他中断打断、处理的任务对时间敏感或处理的任务与硬件有关,那么可以放到上半部,其余以外的其他任务,优先考虑放到下半部

二、添加设备树

打开原理图找到KEY

 可以看到KEY0是接到UART1 CTS上

打开参考手册,找到IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B

看到是可以复用为GPIO1_IO18的

根据之前key驱动实验编写的key节点,添加 184-185两行

184行, 指定父中断,也就是中断控制器,因为key复用为GPIO1_IO18,所以为gpio1

185行,设置中断源,指定中断号,触发方式。因为复用GPIO1_IO18,所以为18,

        IRQ_TYPE_EDGE_BOTH 定义在文件 include/linux/irq.h 中

 IRQ_TYPE_EDGE_BOTH 表示上升沿和下降沿同时有效,相当于KEY0 按下和释放都会触发中断

添加完成之后编译设备树,用此设备树启动

三、编写驱动

导入模板,修改makefile

1、定义宏

 2、编写一个key结构体

irq_desc为中断描述符,这里是key,所以用irq_keydesc 

3、imx6uirq设备添加成员 

在imx6uirq设备中使用,用数组的形式主要是方便添加多个按键

4、按键中断处理函数

实现key结构体中的按键中断处理函数

71行,中断处理函数格式如下

irqreturn_t (*irq_handler_t) (int, void *)

 第一个参数是要中断处理函数要相应的中断号。第二个参数是一个指向 void 的指针,也就是个通用指针,用于区分共享中断的不同设备,也可以指向设备数据结构。中断处理函数的返回值为 irqreturn_t 类型。

73行,dev_id指向dev的设备,也就是imx6uirq

74行,获取gpio的值

5、按键初始化

 

 88行,通过路径查找设备树节点

93-94行,通过循环来进行获取关于节点属性

100-103行,通过循环初始化名字数组;sprintf()用来作格式化的输出;申请使用gpio

109行,设置gpio输出

111行和113行作用一样,都是获取中断号,前者只能利用gpio获取,后者利用通过属性索引获取

116行,设置key0的中断处理函数

117行,设置key0的按键值

120行,在 Linux 内核中要想使用某个中断是需要申请的, request_irq 函数用于申请中断,request_irq函数可能会导致睡眠,因此不能在中断上下文或者其他禁止睡眠的代码段中使用 request_irq 函数。 request_irq 函数会激活(使能)中断,所以不需要我们手动去使能中断, request_irq 函数原型如下:

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 的话表示中断已经
被申请了
 

6、在驱动入口添加初始化

7、 驱动出口函数

 代码如下

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/slab.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/atomic.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/string.h>
#include <linux/irq.h>
#include <linux/interrupt.h>#define IMX6UIRQ_CNT 1
#define IMX6UIRQ_NAME "imx6uirq"
#define KEY_NUM 1       /* 按键数量 	*/
#define KEY0VALUE 0X01  /* KEY0按键值 	*/
#define INVAKEY 0XFF    /* 无效的按键值 *//*key结构体*/
struct irq_keydesc{int gpio;  /*io编号*/int irqnum; /*中断号*/unsigned char value; /*键值*/char name[10]; /*名字*/irqreturn_t(*handler) (int ,void *); /*中断处理函数*/
};struct imx6uirq_dev{dev_t devid;int major;int minor;struct cdev cdev;struct class *class;struct device *device;struct device_node *nd;struct irq_keydesc irqkey[KEY_NUM];
}imx6uirq;
static int imx6uirq_open(struct inode *inode, struct file *filp){filp->private_data = &imx6uirq;return 0;
}
static ssize_t imx6uirq_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{return 0;
}
static ssize_t imx6uirq_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{return 0;
}
static int imx6uirq_release(struct inode *inode, struct file *filp){return 0;
}static const  struct file_operations imx6uirq_fops = {.owner	=   THIS_MODULE,.open   =   imx6uirq_open,.read   =   imx6uirq_read,.write  =   imx6uirq_write,.release =  imx6uirq_release,
};
/*按键中段处理函数*/
static irqreturn_t key0_handler(int irq,void *dev_id){int value = 0;struct imx6uirq_dev * dev = dev_id;value = gpio_get_value(dev->irqkey[0].gpio);if(value == 0){/*按下*/printk("KEY0 push\r\n");}else if(value == 1){/*释放*/printk("KEY0 release\r\n");}return IRQ_HANDLED;
}
/*按鍵初始化*/
static int keyio_init(struct imx6uirq_dev *dev){int i,ret =0 ;/*按鍵初始化*/dev->nd = of_find_node_by_path("/key");if(dev->nd == NULL){ret = -EINVAL;goto fail_nd;}for(i=0;i<KEY_NUM;i++){dev->irqkey[i].gpio = of_get_named_gpio(dev->nd,"key-gpios",i);if(dev->irqkey[i].gpio < 0){ret = -EINVAL;goto fail_gpio;}}for(i=0;i<KEY_NUM;i++){memset(dev->irqkey[i].name,0,sizeof(dev->irqkey[i].name));sprintf(dev->irqkey[i].name,"KEY%d",i);ret = gpio_request(dev->irqkey[i].gpio , dev->irqkey[i].name);if(ret){ret = -EBUSY;printk("IO %d can't request\r\n",dev->irqkey[i].gpio);goto fail_request;}gpio_direction_input(dev->irqkey[i].gpio);/*获取中断号*/dev->irqkey[i].irqnum = gpio_to_irq(dev->irqkey[i].gpio);
#if 0dev->irqkey[i].irqnum = irq_of_parse_and_map(dev->nd,i);#endif}dev->irqkey[0].handler = key0_handler;dev->irqkey[0].value   = KEY0VALUE;/*按键中断初始化*/for(i=0;i<KEY_NUM;i++){ret = request_irq(dev->irqkey[i].irqnum,dev->irqkey[i].handler,IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING,dev->irqkey[i].name,&imx6uirq);if(ret){printk("irq %d request failed!\r\n",dev->irqkey[i].irqnum);goto fail_irq;}}return 0;
fail_irq:for(i=0;i<KEY_NUM;i++){gpio_free(dev->irqkey[i].gpio);}
fail_request:
fail_gpio:
fail_nd:return ret;
}static int __init imx6uirq_init(void){int ret = 0;imx6uirq.major = 0;if(imx6uirq.major){imx6uirq.devid =MKDEV(imx6uirq.major,0);ret = register_chrdev_region(imx6uirq.devid,IMX6UIRQ_CNT,IMX6UIRQ_NAME);if(ret < 0){goto fail_devid;}}else{ret = alloc_chrdev_region(&imx6uirq.devid,0,IMX6UIRQ_CNT,IMX6UIRQ_NAME);if(ret < 0){goto fail_devid;}imx6uirq.major = MAJOR(imx6uirq.devid);imx6uirq.minor = MINOR(imx6uirq.devid);printk("imx6uirq major = %d, minor = %d\r\n", imx6uirq.major, imx6uirq.minor);}imx6uirq.cdev.owner = THIS_MODULE;cdev_init(&imx6uirq.cdev, &imx6uirq_fops);ret = cdev_add(&imx6uirq.cdev,imx6uirq.devid,IMX6UIRQ_CNT);if(ret){goto fail_cdevadd;}imx6uirq.class = class_create(THIS_MODULE,IMX6UIRQ_NAME);if(IS_ERR(imx6uirq.class)){ret = PTR_ERR(imx6uirq.class);goto fail_class;}imx6uirq.device = device_create(imx6uirq.class,NULL,imx6uirq.devid,NULL,IMX6UIRQ_NAME);if(IS_ERR(imx6uirq.device)){ret = PTR_ERR(imx6uirq.device);goto fail_device;}/*初始化IO*/ret = keyio_init(&imx6uirq);if(ret < 0){goto fail_keyinit;}return 0;
fail_keyinit:device_destroy(imx6uirq.class,IMX6UIRQ_CNT);
fail_device:class_destroy(imx6uirq.class);
fail_class:cdev_del(&imx6uirq.cdev);
fail_cdevadd:unregister_chrdev_region(imx6uirq.devid,IMX6UIRQ_CNT);
fail_devid:return ret;
}
static void __exit imx6uirq_exit(void){int i=0;/*释放中断*/for(i=0;i<KEY_NUM;i++){free_irq(imx6uirq.irqkey[i].irqnum,&imx6uirq);}/*释放IO*/for(i=0;i<KEY_NUM;i++){gpio_free(imx6uirq.irqkey[i].gpio);}device_destroy(imx6uirq.class,imx6uirq.devid);class_destroy(imx6uirq.class);cdev_del(&imx6uirq.cdev);unregister_chrdev_region(imx6uirq.devid,IMX6UIRQ_CNT);printk("imx6uirq_exit\r\n");
}module_init(imx6uirq_init);
module_exit(imx6uirq_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("ba che kai qi lai");

编译到开发板上,按下按键0,就会打印相关内容,释放也会,注意此处没做消抖

四、利用定时器进行消抖处理

1、添加定时器

 2、修改中断处理函数

 在进入到中断处理后,定时器处理函数会周期延时20毫秒作消抖处理

3、添加定时器处理函数

消抖后判断是否按下按键

4、在按键初始化函数最后添加初始化定时器

 5、驱动出口函数添加删除定时器

加载驱动进行测试之后,按键按下和释放都会相对准确,在按下和释放速度过快就会打印相同信息的情况

五、编写测试app

1、添加原子操作

2、初始化原子变量

3、按下和释放操作

4、读函数操作

总体代码如下

驱动

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/slab.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/atomic.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/string.h>
#include <linux/irq.h>
#include <linux/interrupt.h>#define IMX6UIRQ_CNT 1
#define IMX6UIRQ_NAME "imx6uirq"
#define KEY_NUM 1       /* 按键数量 	*/
#define KEY0VALUE 0X01  /* KEY0按键值 	*/
#define INVAKEY 0XFF    /* 无效的按键值 *//*key结构体*/
struct irq_keydesc{int gpio;  /*io编号*/int irqnum; /*中断号*/unsigned char value; /*键值*/char name[10]; /*名字*/irqreturn_t(*handler) (int ,void *); /*中断处理函数*/
};struct imx6uirq_dev{dev_t devid;int major;int minor;struct cdev cdev;struct class *class;struct device *device;struct device_node *nd;struct irq_keydesc irqkey[KEY_NUM];struct timer_list timer;atomic_t keyvalue;atomic_t releasekey;
}imx6uirq;
static int imx6uirq_open(struct inode *inode, struct file *filp){filp->private_data = &imx6uirq;return 0;
}
static ssize_t imx6uirq_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{int ret = 0;unsigned char keyvalue;unsigned char releasekey;struct imx6uirq_dev *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 ret;
data_error:return -EINVAL;
}
static ssize_t imx6uirq_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{return 0;
}
static int imx6uirq_release(struct inode *inode, struct file *filp){return 0;
}static const  struct file_operations imx6uirq_fops = {.owner	=   THIS_MODULE,.open   =   imx6uirq_open,.read   =   imx6uirq_read,.write  =   imx6uirq_write,.release =  imx6uirq_release,
};
/*按键中断处理函数*/
static irqreturn_t key0_handler(int irq,void *dev_id){struct imx6uirq_dev * dev = dev_id;dev->timer.data = (volatile unsigned long)dev_id;mod_timer(&dev->timer,jiffies + msecs_to_jiffies(20));/*10ms*/return IRQ_HANDLED;
}
/*定时器处理函数*/
static void timer_func(unsigned long arg){int value = 0;struct imx6uirq_dev *dev = (struct imx6uirq_dev *)arg;value = gpio_get_value(dev->irqkey[0].gpio);if(value == 0){/*按下*/atomic_set(&dev->keyvalue,dev->irqkey[0].value);}else if(value == 1){/*释放*/atomic_set(&dev->keyvalue,0x80 | (dev->irqkey[0].value));atomic_set(&dev->releasekey,1);}}
/*按鍵初始化*/
static int keyio_init(struct imx6uirq_dev *dev){int i,ret =0 ;/*按鍵初始化*/dev->nd = of_find_node_by_path("/key");if(dev->nd == NULL){ret = -EINVAL;goto fail_nd;}for(i=0;i<KEY_NUM;i++){dev->irqkey[i].gpio = of_get_named_gpio(dev->nd,"key-gpios",i);if(dev->irqkey[i].gpio < 0){ret = -EINVAL;goto fail_gpio;}}for(i=0;i<KEY_NUM;i++){memset(dev->irqkey[i].name,0,sizeof(dev->irqkey[i].name));sprintf(dev->irqkey[i].name,"KEY%d",i);ret = gpio_request(dev->irqkey[i].gpio , dev->irqkey[i].name);if(ret){ret = -EBUSY;printk("IO %d can't request\r\n",dev->irqkey[i].gpio);goto fail_request;}gpio_direction_input(dev->irqkey[i].gpio);/*获取中断号*/dev->irqkey[i].irqnum = gpio_to_irq(dev->irqkey[i].gpio);
#if 0dev->irqkey[i].irqnum = irq_of_parse_and_map(dev->nd,i);#endif}dev->irqkey[0].handler = key0_handler;dev->irqkey[0].value   = KEY0VALUE;/*按键中断初始化*/for(i=0;i<KEY_NUM;i++){ret = request_irq(dev->irqkey[i].irqnum,dev->irqkey[i].handler,IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING,dev->irqkey[i].name,&imx6uirq);if(ret){printk("irq %d request failed!\r\n",dev->irqkey[i].irqnum);goto fail_irq;}}/*初始化定时器*/init_timer(&imx6uirq.timer);imx6uirq.timer.function = timer_func;return 0;
fail_irq:for(i=0;i<KEY_NUM;i++){gpio_free(dev->irqkey[i].gpio);}
fail_request:
fail_gpio:
fail_nd:return ret;
}static int __init imx6uirq_init(void){int ret = 0;imx6uirq.major = 0;if(imx6uirq.major){imx6uirq.devid =MKDEV(imx6uirq.major,0);ret = register_chrdev_region(imx6uirq.devid,IMX6UIRQ_CNT,IMX6UIRQ_NAME);if(ret < 0){goto fail_devid;}}else{ret = alloc_chrdev_region(&imx6uirq.devid,0,IMX6UIRQ_CNT,IMX6UIRQ_NAME);if(ret < 0){goto fail_devid;}imx6uirq.major = MAJOR(imx6uirq.devid);imx6uirq.minor = MINOR(imx6uirq.devid);printk("imx6uirq major = %d, minor = %d\r\n", imx6uirq.major, imx6uirq.minor);}imx6uirq.cdev.owner = THIS_MODULE;cdev_init(&imx6uirq.cdev, &imx6uirq_fops);ret = cdev_add(&imx6uirq.cdev,imx6uirq.devid,IMX6UIRQ_CNT);if(ret){goto fail_cdevadd;}imx6uirq.class = class_create(THIS_MODULE,IMX6UIRQ_NAME);if(IS_ERR(imx6uirq.class)){ret = PTR_ERR(imx6uirq.class);goto fail_class;}imx6uirq.device = device_create(imx6uirq.class,NULL,imx6uirq.devid,NULL,IMX6UIRQ_NAME);if(IS_ERR(imx6uirq.device)){ret = PTR_ERR(imx6uirq.device);goto fail_device;}/*初始化IO*/ret = keyio_init(&imx6uirq);if(ret < 0){goto fail_keyinit;}/*初始化原子变量*/atomic_set(&imx6uirq.keyvalue,INVAKEY);atomic_set(&imx6uirq.releasekey,0);return 0;
fail_keyinit:device_destroy(imx6uirq.class,IMX6UIRQ_CNT);
fail_device:class_destroy(imx6uirq.class);
fail_class:cdev_del(&imx6uirq.cdev);
fail_cdevadd:unregister_chrdev_region(imx6uirq.devid,IMX6UIRQ_CNT);
fail_devid:return ret;
}
static void __exit imx6uirq_exit(void){int i=0;/*释放中断*/for(i=0;i<KEY_NUM;i++){free_irq(imx6uirq.irqkey[i].irqnum,&imx6uirq);}/*释放IO*/for(i=0;i<KEY_NUM;i++){gpio_free(imx6uirq.irqkey[i].gpio);}del_timer_sync(&imx6uirq.timer);device_destroy(imx6uirq.class,imx6uirq.devid);class_destroy(imx6uirq.class);cdev_del(&imx6uirq.cdev);unregister_chrdev_region(imx6uirq.devid,IMX6UIRQ_CNT);printk("imx6uirq_exit\r\n");
}module_init(imx6uirq_init);
module_exit(imx6uirq_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("ba che kai qi lai");

APP

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>#define CLOSE_CMD _IO(0XEF ,1)  /*关闭命令*/
#define OPEN_CMD _IO(0XEF,2)    /*打开命令*/
#define SETPERIOD_CMD _IO(0XEF,3) /*设置周期*/int main(int argc, char *argv[])
{int fd,ret;char *filename;unsigned char data;/*判断命令行输入参数是否正确*/if(argc != 2){printf("error usage!\r\n");return -1;}/*用指针指向文件*/filename = argv[1];/*打开文件*/fd = open(filename , O_RDWR);if(fd < 0){printf("file open failed\r\n",filename);return -1;}/*循环读取*/while(1){ret = read(fd,&data,sizeof(data));if(ret<0){}else{if(data)printf(" key vaule = %d\r\n",data);}}/*关闭文件*/close(fd);return 0;
}

相关文章:

Linux 中断实验

目录 一、Linux 中断简介 上半部与下半部 二、添加设备树 三、编写驱动 1、定义宏 2、编写一个key结构体 3、imx6uirq设备添加成员 ​编辑4、按键中断处理函数 5、按键初始化 6、在驱动入口添加初始化 7、 驱动出口函数 代码如下 四、利用定时器进行消抖处理 1、添…...

【c++】指针

文章目录指针的定义和使用指针所占的内存空间空指针野指针const修饰指针指针和数组指针和函数指针、数组、函数案例&#xff1a;冒泡排序指针的定义和使用 指针定义的语法&#xff1a;数据类型 * 指针变量名 使用指针&#xff1a; 可以通过解引用的方式来找到指针指向的内存&…...

别具一格的婚礼,VR全景+婚礼的优势展现在哪里?

随着90后、95后逐渐步入结婚的主力军中&#xff0c;如何策划一场别具一格的婚礼是许多年轻人所头疼的&#xff0c;那么今年我们就可以玩点新潮的&#xff0c;VR婚礼或许是个不错的选择。 VR全景婚礼就是通过全景摄像机对婚礼进行记录&#xff0c;不但可以帮助新人捕捉婚礼的精彩…...

【GD32F427开发板试用】5. SPI驱动TFTLCD屏幕

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;hehung 之前发帖 【GD32F427开发板试用】1. 串口实现scanf输入控制LED 【GD32F427开发板试用】2. RT-Thread标准版移植 【GD32F427开发板试用…...

测试2年还拿实习生的薪资打发我,你后悔去吧····

20年7月大学毕业&#xff0c;学的计算机科学专业。因为考研之后&#xff0c;秋招结束了。没什么更多的岗位选择&#xff0c;就想找个工作先干着&#xff0c;然后亲戚在一家大厂公司上班说要招测试&#xff0c;所以就来做测试了。 虽然都是属于计算机大类&#xff0c;但自己专业…...

面向对象程序(C++)设计基础

一、类&对象C 在 C 语言的基础上增加了面向对象编程&#xff0c;C 支持面向对象程序设计。类是 C 的核心特性&#xff0c;通常被称为用户定义的类型。类提供了对象的蓝图&#xff0c;所以基本上&#xff0c;对象是根据类来创建的。声明类的对象&#xff0c;就像声明基本类型…...

conda安装nodejs版本过低解决方法

conda命令直接安装nodejs时&#xff0c;可能会由于镜像源中nodejs版本过低导致没法安装高本版的nodejs&#xff0c;导致无法jupyterlab使用一些扩展插件。 解决方法如下&#xff1a;&#xff08;windows环境下直接按提示下载版本安装就行&#xff0c;此处只介绍linux环境的解决…...

前端工程师leetcode算法面试必备-二分搜索算法(下)索算法(下)

一、287. 寻找重复数 给定一个包含 n 1 个整数的数组 nums&#xff0c;其数字都在 1 到 n 之间&#xff08;包括 1 和 n&#xff09;&#xff0c;可知至少存在一个重复的整数。假设只有一个重复的整数&#xff0c;找出这个重复的数。 1、HashMap 在没有其它附加条件的情况下&…...

使用Autowired为什么会被IDEA警告,应该怎么修改最佳

问题原因 关于这个问题&#xff0c;其实答案相对统一&#xff0c;实际上用大白话说起来也容易理解。 初始化问题 先看一下Java初始化类的顺序&#xff1a;父类的静态字段 > 父类静态代码块 > 子类静态字段 > 子类静态代码块 > 父类成员变量 > 父类构造代码块 &…...

面向对象(中)

面向对象&#xff08;中&#xff09; 一、 面向对象之继承性 继承性的好处 减少代码的冗余&#xff0c;提高了代码的复用性。 便于功能的扩展。 为多态性的使用&#xff0c;提供了前提。 继承性的格式 class A extends B{} A&#xff1a;子类、派生类、subclass B&#xff1a…...

【云原生】promehtheus整合grafana实现可视化监控实战

文章目录前言一. 实验环境二. 安装grafana2.1 grafana的介绍2.2 为什么选择grafana&#xff1f;2.3 grafana下载及安装三. 网页端配置grafana3.1 浏览器访问grafana网页3.2 使用grafana 获取prometheus的数据源3.3 grafana导入prometheus模板总结前言 大家好&#xff0c;又见面…...

Linux 内核定时器实验

目录 一、内核时间管理简介 二、内核定时器简介 三、驱动编写 1、修改makefile 2、添加定义 3、初始化led函数 4、添加调用 5、初始化定时器与定时器处理函数 这部分代码如下 四、ioctl函数 五、内核添加unlocked_ioctl 函数 1、添加设备操作集unlocked_ioctl成员 2…...

喜欢大屏电视?那就选择酷开系统,实现智能生活享受

随着科技的发展和我们生活水平的提高&#xff0c;越来越多的消费者开始认可并习惯使用各种高质量的科技产品&#xff0c;比如喜欢玩游戏的消费者&#xff0c;他们往往会追求流畅性更强、刷新率更快的大显示屏&#xff0c;以此获得更真实刺激的游戏体验&#xff0c;而喜欢追剧的…...

PMP应该如何备考?

备考之初的我们&#xff0c;总会四处搜索PMP备考经验&#xff0c;希望能拿到那些高分通关前辈的备考经验和方法。众所周知PMP考试因为有35个学时培训的基本要求&#xff0c;所以肯定是要通过培训机构报名的。 一&#xff0c;首先我们需要了解到新的考纲 1.PMP模块划分发生变化…...

AcWing《蓝桥杯集训·每日一题》—— 3956.截断数组

AcWing《蓝桥杯集训每日一题》—— 3956. 截断数组 文章目录AcWing《蓝桥杯集训每日一题》—— 3956. 截断数组一、题目二、解题思路三、代码实现本次博客我是通过Notion软件写的&#xff0c;转md文件可能不太美观&#xff0c;大家可以去我的博客中查看&#xff1a;北天的 BLOG…...

Docker的数据管理

一、管理docker容器中数据 管理Docker 容器中数据主要有两种方式:数据卷(Data Volumes)和数据卷容器( DataVolumes Containers) 。 1、 数据卷 数据卷是一个供容器使用的特殊目录&#xff0c;位于容器中。可将宿主机的目录挂载到数据卷上&#xff0c;对数据卷的修改操作立刻…...

RxJS处理异步数据流

什么是异步? 异步&#xff08;Asynchronous&#xff09;指的是不同步发生的事件或操作。通常&#xff0c;同步操作是指一系列代码按照顺序依次执行&#xff0c;直到当前代码块执行完毕后才继续执行下一个代码块&#xff1b;而异步操作则是指某些代码会被提交到后台执行&#…...

IP地址与用户行为

IP地址能够解决网络风险和提高网络安全的原因是&#xff1a;所有的网络请求都会带有IP信息&#xff0c;是访问者的独立标识&#xff0c;另外ip地址的分配和管理比较严格&#xff0c;难以造假。另外ip属于网络层&#xff0c;可以轻松的对其进行阻断。现有的各种网络安全、负载均…...

底层逻辑2

有些创业者&#xff0c;在3D打印⽕爆的时候做3D打印&#xff0c;在VR&#xff08;虚拟现 实&#xff09;蓬勃发展的时候转⾏做VR&#xff0c;在区块链成为热⻔话题的时候摇身⼀ 变成了区块链专家&#xff0c;⽽⼈⼯智能⽕了以后&#xff0c;他们⼜全身⼼投⼊⼈⼯智 能这⼀⾏。再…...

TCP报头详解及TCP十种核心机制(一)

目录 前言&#xff1a; TCP报头 TCP核心机制 一、确认应答 二、超时重传 小结&#xff1a; 前言&#xff1a; 这篇文章详细介绍了TCP报头中的一些核心数据&#xff0c;及两种TCP核心机制。其他的一些机制会在后面文章中详细介绍。 TCP报头 解释&#xff1a; 1&#xff…...

Linux用户的添加、修改和删除以及相关配置文件:useradd、passwd、usermod、userdel、相关配置文件

目录 账户的创建&#xff08;useradd&#xff09; 第一步&#xff1a;创建账号 第二步&#xff1a;创建密码 useradd参考文件 CROUP100 HOME/home INACTIVE-1 EXPIRE SHELL/bin/bash SKEL/etc/skel UID/GID密码参数参考&#xff1a;/etc/login.defs 密码参数显示命…...

进程地址空间

目录 回顾C/C语言的程序地址空间 感性认识虚拟地址空间 虚拟地址空间与物理空间如何建立映射关系 为什么要虚拟地址空间&#xff1f; 回顾C/C语言的程序地址空间 在学习C/C语言时我们知道了一个概念叫程序地址空间。通俗来说就是如下一张表&#xff0c;从中可以得知系统的几…...

数楼梯(加强版)

数楼梯(加强版) 题目背景: 小明一天放学回家,看到从1楼到2楼共有n个台阶,因为好奇,他想尝试一下总共有几种方案到二楼?他可以1步,2步,3步的跳,不能跳3步以上. 他试了很多次都没有解决这个问题,于是请求聪明的你帮忙解决这个问题. 题目描述: 1楼到2楼楼梯有n级台阶。小明每…...

MySQL-数据类型

数据类型简介数据表由多列字段构成&#xff0c;每一个字段指定了不同的数据类型&#xff0c;指定了数据类型之后&#xff0c;也就决定了向字段插入的数据内容。不同的数据类型也决定了 MySQL 在存储它们的时候使用的方式&#xff0c;以及在使用它们的时候选择什么运算符号进行运…...

剑指 Offer 32 - II. 从上到下打印二叉树 II(java解题)

剑指 Offer 32 - II. 从上到下打印二叉树 II&#xff08;java解题&#xff09;1. 题目2. 解题思路3. 数据类型功能函数总结4. java代码5. 踩坑记录1. 题目 从上到下按层打印二叉树&#xff0c;同一层的节点按从左到右的顺序打印&#xff0c;每一层打印到一行。 例如: 给定二叉…...

C#网络爬虫开发

1前言爬虫一般都是用Python来写&#xff0c;生态丰富&#xff0c;动态语言开发速度快&#xff0c;调试也很方便但是我要说但是&#xff0c;动态语言也有其局限性&#xff0c;笔者作为老爬虫带师&#xff0c;几乎各种语言都搞过&#xff0c;现在这个任务并不复杂&#xff0c;用我…...

Fastjson 总结

0x00 前言 这一篇主要是针对已经完成的fastjson系列做一个知识点总结&#xff0c;一来是为了更加有条理的梳理已经存在的内容&#xff0c;二来是为了更好的复习和利用。 0x01 Fastjson基础知识点 1.常见问题&#xff1a; 问&#xff1a;fastjson的触发点是什么&#xff1f;…...

文件路径模块os.path

文件路径模块os.path 文章目录文件路径模块os.path1.概述2.解析路径2.1.拆分路径和文件名split2.2.获取文件名称basename2.3.返回路径第一部分dirname2.4.扩展名称解析路径splitext2.5.返回公共前缀路径commonprefix3.创建路径3.1.拼接路径join3.2.获取家目录3.3.规范化路径nor…...

Kerberos简单介绍及使用

Kerberos作用 简单来说安全相关一般涉及以下方面&#xff1a;用户认证&#xff08;Kerberos的作用&#xff09;、用户授权、用户管理.。而Kerberos功能是用户认证&#xff0c;通俗来说解决了证明A是A 的问题。 认证过程&#xff08;时序图&#xff09; 核心角色/概念 KDC&…...

DOM编程-全选、全不选和反选

<!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>全选、全不选和反选</title> </head> <body bgcolor"antiquewhite"> <script type"text/jav…...

图片网站如何做百度排名/seo教程排名第一

2021新的一年&#xff0c;开启新的征程&#xff0c;回顾2020&#xff0c;真是太“南”了。 从年初各大厂裁员&#xff0c;竟然成为一件理所应当的事情&#xff0c;到四月份 GitHub 上“996.ICU” 引起了大家的共鸣。即使我们兢兢业业“996”&#xff0c;但依旧难以抵御 35 岁时…...

赣州做网站建设/东莞seo建站如何推广

前言 在上一篇开始Java8之旅(六) -- 使用lambda实现Java的尾递归中&#xff0c;我们利用了函数的懒加载机制实现了栈帧的复用&#xff0c;成功的实现了Java版本的尾递归&#xff0c;然而尾递归的使用有一个重要的条件就是递归表达式必须是在函数的尾部&#xff0c;但是在很多实…...

服务器ip做网站/企业网站建设的作用

为什么80%的码农都做不了架构师&#xff1f;>>> 通过为防火墙提供有关对来自某个源&#xff0c;到某个目的地或具有特定协议类型的信息包要执行操作的指令及规则控制信息包的过滤。通过使用Netfilter/iptables系统提供的特殊命令iptables建立这些规则&#xff0c;并…...

网站没备案做淘宝客/制作网站需要什么技术

一、数据类型 作用 声明函数和变量为了把数据分成所需内存大小不同的数据&#xff0c;编程的时候需要用大数据的时候才需要申请大内存&#xff0c;就可以充分利用内存。 二、数据类型–布尔型 值 truefalse。 一个简单的例子&#xff1a; var b bool true三、数据类型–数…...

西宁 专业网站建设/上海seo关键词优化

import shelvefshelve.open(rshelve)#f[stu_info] {name:john,age:18} #f[stu2_info] {name:tom,age:20} #f[stu3_info] {name:jey,age:19} #f.close()print(f.get(stu_info)[name]) 转载于:https://www.cnblogs.com/liujinjing521/p/11320632.html...

上海社区网站建设/郑州模板建站代理

web程序在linux服务器上的发布方法方法 step1 数据库设置从开发环境改成生产环境(根据您的参数来配置。) // An highlighted block #生产环境 c3p0.datasource.jdbcUrljdbc:mysql://localhost:3306/ext_upload_files?serverTimezoneAsia/Shanghai&useUnicodetrue&c…...