STM32MP157A單片機移植Linux驅動

在stm32mp157a單片機移植Linux操作系統,并移植內核驅動,在應用程序中使用3個線程,分別實現控制單片機上3個led流水燈的功能、蜂鳴器控制的功能、風扇控制的功能。

需求整理:

1.驅動程序-->led1.c,led2.c,led3.c,beep.c,fan.c。實現對led字符設備驅動的注冊(register_chrdev)和注銷(unregister_chrdev)功能、對字符設備相關操作方法的封裝(用戶空間和內核空間進行數據傳遞-->copy_to_user,copy_from_user)、物理內存映射虛擬內存(ioremap,iounmap),通過原理圖可知---led1->PE10,led2->PF10,led3->PE8,beep->PB6,fan->PE9;

2.頭文件-->led.h,beep.h,fan.h。物理內存的寄存器地址;

3.腳本文件生成驅動程序-->Makefile-->生成led1.ko,led2.ko,led3.ko,beep.ko,fan.ko;

4.流水燈應用程序-->application_test.c。使用3個線程實現對led流水燈的控制、蜂鳴器控制、風扇控制。

5.shell命令創建設備文件-->/dev/led1,/dev/led2,/dev/led3,/dev/beep,/dev/fan。用于流水燈應用程序對led的文件描述符。

分析:

僅使用open、write、read、close對io進行控制,直接在write對應的回調函數中進行數據處理,再此基礎上實現多線程驅動的邏輯代碼。

方案實現:
1.驅動程序
led1.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include "led.h"//字符設備描述符
unsigned int major;
//接收數據buf
char myled1_buf[128] = {};
//虛擬映射寄存器地址
unsigned int* vir_rcc;
unsigned int* vir_moder;
unsigned int* vir_odr;int myled1_open(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
//
ssize_t myled1_write(struct file *file, const char __user *ubuf, size_t size, loff_t *lft)
{unsigned long n = copy_from_user(myled1_buf, ubuf, size);if (n > 0){printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return n;}	//printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);if (myled1_buf[0] == 1){(*vir_odr) |= (0x1<<10);	//高電平}else if (myled1_buf[0] == 0){(*vir_odr) &=  (~(0x1<<10));	//低電平}return 0;
}ssize_t myled1_read(struct file *file, char __user *ubuf, size_t size, loff_t *lft)
{unsigned long n = copy_to_user(ubuf, myled1_buf, size);if (n > 0){printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return n;}printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}int myled1_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
//定義字符設備的回調函數接口
struct file_operations fops = {.open    = myled1_open,  .read    = myled1_read,  .write   = myled1_write, .release = myled1_close,                                 
};//字符設備注冊
static int __init myled1_init(void)
{major = register_chrdev(0, "myled1", &fops);if (major < 0){printk("字符設備注冊失敗\n");}printk("字符設備注冊成功 major = %d\n", major);//硬件寄存器映射到虛擬寄存器地址 ioremapvir_rcc = ioremap(PHY_RCC_GPIO, 4);if (vir_rcc == NULL){printk("硬件寄存器映射失敗:%d\n", __LINE__);return -1;}vir_moder = ioremap(PHY_GPIOE_MODER, 4);if (vir_moder == NULL){printk("硬件寄存器映射失敗:%d\n", __LINE__);iounmap(vir_rcc);return -1;}vir_odr = ioremap(PHY_GPIOE_ODR, 4);if (vir_odr == NULL){printk("硬件寄存器映射失敗:%d\n", __LINE__);iounmap(vir_rcc);iounmap(vir_moder);return -1;}printk("物理內存映射成功\n");//初始化PE10(*vir_rcc) |= (0x1<<4);	//使能rcc(*vir_moder) &= (~(0x3<<20));(*vir_moder) |= (0x1<<20);(*vir_odr) &=  (~(0x1<<10));//默認低電平return 0;
}
//字符設備注銷
static void __exit myled1_exit(void)
{iounmap(vir_rcc);iounmap(vir_moder);iounmap(vir_odr);unregister_chrdev(major, "myled1");printk("字符設備注銷成功\n");
}
//模塊
module_init(myled1_init);
module_exit(myled1_exit);
//遵循GPL開源協議
MODULE_LICENSE("GPL");
led2.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include "led.h"unsigned int major;
char myled2_buf[128] = {};
unsigned int* vir_rcc;
unsigned int* vir_moder;
unsigned int* vir_odr;int myled2_open(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
//
ssize_t myled2_write(struct file *file, const char __user *ubuf, size_t size, loff_t *lft)
{unsigned long n = copy_from_user(myled2_buf, ubuf, size);if (n > 0){printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return n;}	//printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);if (myled2_buf[0] == 1){(*vir_odr) |= (0x1<<10);	//高電平}else if (myled2_buf[0] == 0){(*vir_odr) &=  (~(0x1<<10));	//低電平}return 0;
}ssize_t myled2_read(struct file *file, char __user *ubuf, size_t size, loff_t *lft)
{unsigned long n = copy_to_user(ubuf, myled2_buf, size);if (n > 0){printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return n;}printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}int myled2_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}struct file_operations fops = {.open    = myled2_open,  .read    = myled2_read,  .write   = myled2_write, .release = myled2_close,                                 
};static int __init myled2_init(void)
{major = register_chrdev(0, "myled2", &fops);if (major < 0){printk("字符設備注冊失敗\n");}printk("字符設備注冊成功 major = %d\n", major);//硬件寄存器映射到虛擬寄存器地址 ioremapvir_rcc = ioremap(PHY_RCC_GPIO, 4);if (vir_rcc == NULL){printk("硬件寄存器映射失敗:%d\n", __LINE__);return -1;}vir_moder = ioremap(PHY_GPIOF_MODER, 4);if (vir_moder == NULL){printk("硬件寄存器映射失敗:%d\n", __LINE__);iounmap(vir_rcc);return -1;}vir_odr = ioremap(PHY_GPIOF_ODR, 4);if (vir_odr == NULL){printk("硬件寄存器映射失敗:%d\n", __LINE__);iounmap(vir_rcc);iounmap(vir_moder);return -1;}printk("物理內存映射成功\n");//初始化PF10(*vir_rcc) |= (0x1<<5);	//使能rcc(*vir_moder) &= (~(0x3<<20));(*vir_moder) |= (0x1<<20);(*vir_odr) &=  (~(0x1<<10));//默認低電平return 0;
}static void __exit myled2_exit(void)
{iounmap(vir_rcc);iounmap(vir_moder);iounmap(vir_odr);unregister_chrdev(major, "myled2");printk("字符設備注銷成功\n");
}module_init(myled2_init);
module_exit(myled2_exit);
MODULE_LICENSE("GPL");
?led3.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include "led.h"unsigned int major;
char myled3_buf[128] = {};
unsigned int* vir_rcc;
unsigned int* vir_moder;
unsigned int* vir_odr;int myled3_open(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
//
ssize_t myled3_write(struct file *file, const char __user *ubuf, size_t size, loff_t *lft)
{unsigned long n = copy_from_user(myled3_buf, ubuf, size);if (n > 0){printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return n;}	//printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);if (myled3_buf[0] == 1){(*vir_odr) |= (0x1<<8);	//高電平}else if (myled3_buf[0] == 0){(*vir_odr) &=  (~(0x1<<8));	//低電平}return 0;
}ssize_t myled3_read(struct file *file, char __user *ubuf, size_t size, loff_t *lft)
{unsigned long n = copy_to_user(ubuf, myled3_buf, size);if (n > 0){printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return n;}printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}int myled3_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}struct file_operations fops = {.open    = myled3_open,  .read    = myled3_read,  .write   = myled3_write, .release = myled3_close,                                 
};static int __init myled3_init(void)
{major = register_chrdev(0, "myled3", &fops);if (major < 0){printk("字符設備注冊失敗\n");}printk("字符設備注冊成功 major = %d\n", major);//硬件寄存器映射到虛擬寄存器地址 ioremapvir_rcc = ioremap(PHY_RCC_GPIO, 4);if (vir_rcc == NULL){printk("硬件寄存器映射失敗:%d\n", __LINE__);return -1;}vir_moder = ioremap(PHY_GPIOE_MODER, 4);if (vir_moder == NULL){printk("硬件寄存器映射失敗:%d\n", __LINE__);iounmap(vir_rcc);return -1;}vir_odr = ioremap(PHY_GPIOE_ODR, 4);if (vir_odr == NULL){printk("硬件寄存器映射失敗:%d\n", __LINE__);iounmap(vir_rcc);iounmap(vir_moder);return -1;}printk("物理內存映射成功\n");//初始化PE8(*vir_rcc) |= (0x1<<4);	//使能rcc(*vir_moder) &= (~(0x3<<16));(*vir_moder) |= (0x1<<16);(*vir_odr) &=  (~(0x1<<8));//默認低電平return 0;
}static void __exit myled3_exit(void)
{iounmap(vir_rcc);iounmap(vir_moder);iounmap(vir_odr);unregister_chrdev(major, "myled3");printk("字符設備注銷成功\n");
}module_init(myled3_init);
module_exit(myled3_exit);
MODULE_LICENSE("GPL");
beep.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include "beep.h"unsigned int major;
char mybeep_buf[128] = {};
unsigned int* vir_rcc;
unsigned int* vir_moder;
unsigned int* vir_odr;int mybeep_open(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
//
ssize_t mybeep_write(struct file *file, const char __user *ubuf, size_t size, loff_t *lft)
{unsigned long n = copy_from_user(mybeep_buf, ubuf, size);if (n > 0){printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return n;}		printk("%s:%s:%d:mybeep_buf=%d\n", __FILE__, __func__, __LINE__, mybeep_buf[0]);if (mybeep_buf[0] == 1){(*vir_odr) |= (0x1<<6);	//高電平}else if (mybeep_buf[0] == 0){(*vir_odr) &=  (~(0x1<<6));	//低電平}return 0;
}ssize_t mybeep_read(struct file *file, char __user *ubuf, size_t size, loff_t *lft)
{unsigned long n = copy_to_user(ubuf, mybeep_buf, size);if (n > 0){printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return n;}//printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}int mybeep_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
} struct file_operations fops = {.open    = mybeep_open,  .read    = mybeep_read,  .write   = mybeep_write, .release = mybeep_close,    
};static int __init mybeep_init(void)
{major = register_chrdev(0, "mybeep", &fops);if (major < 0){printk("字符設備注冊失敗\n");}printk("字符設備注冊成功 major = %d\n", major);//硬件寄存器映射到虛擬寄存器地址 ioremapvir_rcc = ioremap(PHY_RCC_GPIO, 4);if (vir_rcc == NULL){printk("硬件寄存器映射失敗:%d\n", __LINE__);return -1;}vir_moder = ioremap(PHY_GPIOB_MODER, 4);if (vir_moder == NULL){printk("硬件寄存器映射失敗:%d\n", __LINE__);iounmap(vir_rcc);return -1;}vir_odr = ioremap(PHY_GPIOB_ODR, 4);if (vir_odr == NULL){printk("硬件寄存器映射失敗:%d\n", __LINE__);iounmap(vir_rcc);iounmap(vir_moder);return -1;}printk("物理內存映射成功\n");//初始化PB6(*vir_rcc) |= (0x1<<1);	//使能rcc(*vir_moder) &= (~(0x3<<12));(*vir_moder) |= (0x1<<12);(*vir_odr) &=  (~(0x1<<6));//默認低電平return 0;
}static void __exit mybeep_exit(void)
{iounmap(vir_rcc);iounmap(vir_moder);iounmap(vir_odr);unregister_chrdev(major, "mybeep");printk("字符設備注銷成功\n");
}module_init(mybeep_init);
module_exit(mybeep_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Johnson");
MODULE_DESCRIPTION("A simple Linux char driver for beep control");
MODULE_VERSION("1.0");
fan.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include "fan.h"unsigned int major;
char myfan_buf[128] = {};
unsigned int* vir_rcc;
unsigned int* vir_moder;
unsigned int* vir_odr;int myfan_open(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
//
ssize_t myfan_write(struct file *file, const char __user *ubuf, size_t size, loff_t *lft)
{unsigned long n = copy_from_user(myfan_buf, ubuf, size);if (n > 0){printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return n;}	printk("%s:%s:%d:myfan_buf[0]=%d\n", __FILE__, __func__, __LINE__, myfan_buf[0]);if (myfan_buf[0] == 1){(*vir_odr) |= (0x1<<9);	//高電平}else if (myfan_buf[0] == 0){(*vir_odr) &=  (~(0x1<<9));	//低電平}return 0;
}ssize_t myfan_read(struct file *file, char __user *ubuf, size_t size, loff_t *lft)
{unsigned long n = copy_to_user(ubuf, myfan_buf, size);if (n > 0){printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return n;}printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}int myfan_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}struct file_operations fops = {.open    = myfan_open,  .read    = myfan_read,  .write   = myfan_write, .release = myfan_close,                                 
};static int __init myfan_init(void)
{major = register_chrdev(0, "myfan", &fops);if (major < 0){printk("字符設備注冊失敗\n");}printk("字符設備注冊成功 major = %d\n", major);//硬件寄存器映射到虛擬寄存器地址 ioremapvir_rcc = ioremap(PHY_RCC_GPIO, 4);if (vir_rcc == NULL){printk("硬件寄存器映射失敗:%d\n", __LINE__);return -1;}vir_moder = ioremap(PHY_GPIOE_MODER, 4);if (vir_moder == NULL){printk("硬件寄存器映射失敗:%d\n", __LINE__);iounmap(vir_rcc);return -1;}vir_odr = ioremap(PHY_GPIOE_ODR, 4);if (vir_odr == NULL){printk("硬件寄存器映射失敗:%d\n", __LINE__);iounmap(vir_rcc);iounmap(vir_moder);return -1;}printk("物理內存映射成功\n");//初始化PE9(*vir_rcc) |= (0x1<<4);	//使能rcc(*vir_moder) &= (~(0x3<<18));(*vir_moder) |= (0x1<<18);(*vir_odr) &=  (~(0x1<<9));//默認低電平return 0;
}static void __exit myfan_exit(void)
{iounmap(vir_rcc);iounmap(vir_moder);iounmap(vir_odr);unregister_chrdev(major, "myfan");printk("字符設備注銷成功\n");
}module_init(myfan_init);
module_exit(myfan_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Johnson");
MODULE_DESCRIPTION("A simple Linux char driver for fan control");
MODULE_VERSION("1.0");
2.頭文件

由于都是控制GPIO,使能相同的RCC時鐘,為便利這里分為3個頭文件。

led.h
#ifndef __LED_H__
#define __LED_H__#define PHY_RCC_GPIO	0x50000a28
#define PHY_GPIOE_MODER	0X50006000
#define PHY_GPIOE_ODR	0X50006014
#define PHY_GPIOF_MODER 0x50007000
#define PHY_GPIOF_ODR	0x50007014#endif
beep.h
#ifndef __BEEP_H__
#define __BEEP_H__#define PHY_RCC_GPIO	0x50000a28
#define PHY_GPIOB_MODER	0X50003000
#define PHY_GPIOB_ODR	0X50003014#endif
fan.h
#ifndef __FAN_H__
#define __FAN_H__#define PHY_RCC_GPIO	0x50000a28
#define PHY_GPIOE_MODER	0X50006000
#define PHY_GPIOE_ODR	0X50006014#endif
3.Makefile
Makefile
modname ?= led
arch ?= arm
ifeq ($(arch),arm)
KERNELDIR := ~/FSMP1A/stm32mp1-openstlinux-5.4-dunfell-mp1-20-06-24/sources/arm-ostl-linux-gnueabi/linux-stm32mp-5.4.31-r0/linux-5.4.31/
else
KERNELDIR := /lib/modules/$(shell uname -r)/build/
endifPWD := $(shell pwd)all:make -C $(KERNELDIR) M=$(PWD) modulesobj-m = $(modname).o
#obj-m = demo.oclean:make -C $(KERNELDIR) M=$(PWD) clean
4.應用程序
application_test.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>char buf[5] = {};void* led_control(void* args)
{char led1_buf[1] = {};char led2_buf[1] = {};char led3_buf[1] = {};int fd1 = open("/dev/myled1", O_RDWR);if (fd1 < 0){perror("/dev/myled1");pthread_exit(NULL); return 0;}int fd2 = open("/dev/myled2", O_RDWR);if (fd2 < 0){perror("/dev/myled2");close(fd1);pthread_exit(NULL); return 0; }int fd3 = open("/dev/myled3", O_RDWR);if (fd3 < 0){perror("/dev/myled3");close(fd1);close(fd2);pthread_exit(NULL); return 0;}while(1){led1_buf[0] = buf[0];led2_buf[0] = buf[1];led3_buf[0] = buf[2];write(fd1, led1_buf, sizeof(led1_buf));write(fd2, led2_buf, sizeof(led2_buf));write(fd3, led3_buf, sizeof(led3_buf));sleep(1);}close(fd1);close(fd2);close(fd3);pthread_exit(NULL); return 0;
}void* beep_control(void* args)
{char beep_buf[1] = {};int fd1 = open("/dev/mybeep", O_RDWR);if (fd1 < 0){perror("/dev/mybeep");pthread_exit(NULL); return 0;}while(1){beep_buf[0] = buf[3];write(fd1, beep_buf, sizeof(beep_buf));sleep(1);}close(fd1);pthread_exit(NULL); return 0;
}void* fan_control(void* args)
{char fan_buf[1] = {};int fd1 = open("/dev/myfan", O_RDWR);if (fd1 < 0){perror("/dev/myfan");pthread_exit(NULL); return 0;}while(1){fan_buf[0] = buf[4];write(fd1, fan_buf, sizeof(fan_buf));sleep(1);}close(fd1);pthread_exit(NULL); return 0;
}void* main_control(void* args)
{int module, control;while(1){printf("請選擇控制的模塊:1(led1)2(led2)3(led3)4(beep)5(fan)>");scanf("%d", &module);if (module != 1 && module != 2 && module != 3 && module != 4 && module != 5){printf("模塊[%d]不存在\n", module);}switch(module){case 1:printf("模塊[%d]請選擇開燈(1)或關燈(0)>", module);scanf("%d", &control);if (control != 0 && control != 1){printf("輸入錯誤,請重新選擇\n");break;}buf[0] = control;break;case 2:printf("模塊[%d]請選擇開燈(1)或關燈(0)>", module);scanf("%d", &control);if (control != 0 && control != 1){printf("輸入錯誤,請重新選擇\n");break;}buf[1] = control;break;case 3:printf("模塊[%d]請選擇開燈(1)或關燈(0)>", module);scanf("%d", &control);if (control != 0 && control != 1){printf("輸入錯誤,請重新選擇\n");break;}buf[2] = control;break;case 4:printf("模塊[%d]請選擇蜂鳴器響(1)或滅(0)>", module);scanf("%d", &control);if (control != 0 && control != 1){printf("輸入錯誤,請重新選擇\n");break;}buf[3] = control;break;case 5:printf("模塊[%d]請選擇風扇開(1)或關(0)>", module);scanf("%d", &control);if (control != 0 && control != 1){printf("輸入錯誤,請重新選擇\n");break;}buf[4] = control;break;default:break;}sleep(1);}pthread_exit(NULL); return 0;
}int main(int argc, char const *argv[])
{pthread_t threadled, threadbeep, threadfan, threadmain;int thread_led = 10;int thread_beep = 10;int thread_fan = 10;int thread_main = 10;if (pthread_create(&threadled , NULL, led_control, &thread_led) != 0){perror("pthread_create");exit(EXIT_FAILURE);}if (pthread_create(&threadbeep , NULL, beep_control, &thread_beep) != 0){perror("pthread_create");exit(EXIT_FAILURE);}if (pthread_create(&threadfan , NULL, fan_control, &thread_fan) != 0){perror("pthread_create");exit(EXIT_FAILURE);}if (pthread_create(&threadmain , NULL, main_control, &thread_main) != 0){perror("pthread_create");exit(EXIT_FAILURE);}if (pthread_join(threadled, NULL) != 0){perror("pthread_join");exit(EXIT_FAILURE);}if (pthread_join(threadbeep, NULL) != 0){perror("pthread_join");exit(EXIT_FAILURE);}if (pthread_join(threadfan, NULL) != 0){perror("pthread_join");exit(EXIT_FAILURE);}if (pthread_join(threadmain, NULL) != 0){perror("pthread_join");exit(EXIT_FAILURE);}// 主線程退出return 0;
}
5.mknod創建字符設備文件

mknod 字符設備文件名?字符設備類型(c/b) 主設備號?次設備號

mknod /dev/led1 c 主設備號?次設備號

mknod /dev/led2 c 主設備號?次設備號

mknod /dev/led3 c 主設備號?次設備號

mknod /dev/beep c 主設備號?次設備號

mknod /dev/fan c 主設備號?次設備號

在終端執行以上命令創建字符設備文件,否則在應用程序中open無法正常打開字符設備,導致線程退出。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/70420.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/70420.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/70420.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python中格式化輸出知識點匯總

在Python中&#xff0c;格式化輸出是一種常見的操作&#xff0c;用于將數據以特定的格式展示。以下是Python中格式化輸出的主要方法&#xff1a; ### 1. 使用 % 操作符 這是Python早期版本中常用的格式化方法&#xff0c;類似于C語言中的printf。 - **基本語法**&#xff1a;&…

完美轉發使用

完美轉發的幾個例子 例子 1&#xff1a;普通的完美轉發 首先&#xff0c;我們先來一個簡單的完美轉發的例子&#xff0c;展示如何使用 std::forward 來保持傳入參數的類型。 #include <iostream> #include <utility> // std::forwardvoid func(int& x) {st…

【Content-Type詳解、Postman中binary格式、json格式數據轉原始二進制流等】

Content-Type詳解、Postman中binary格式、json格式數據轉原始二進制流等 背景&#xff1a;postman中如何使用binary格式上傳文件 Content-TypeContent-Type的格式由三部分組成&#xff1a;以下是一些常見的Content-Type示例&#xff1a; Postman中 binary格式定義&#xff1a;用…

DeepSeek等大模型功能集成到WPS中的詳細步驟

記錄下將**DeepSeek功能集成到WPS中**的步驟&#xff0c;以備忘。 1. 下載并安裝OfficeAI插件 訪問OfficeAI插件下載地址&#xff1a;https://www.office-ai.cn/&#xff0c;下載插件&#xff08;目前只支持windows系統&#xff09;。 注意&#xff0c;有兩個插件&#xff0…

MATLAB學習之旅:從入門到基礎實踐

在當今科技飛速發展的時代,MATLAB作為一款強大的數學軟件,猶如一把神奇的鑰匙,能夠打開眾多領域的大門。無論是工程計算、數據分析,還是算法開發、可視化呈現,MATLAB都展現出了無與倫比的魅力。今天,就讓我們踏上這段奇妙的MATLAB學習之旅,從最基礎的部分開始,逐步探索…

在Ubutu18.04下搭建nfs服務器

在Ubutu18.04下搭建nfs服務器 主要參考這篇博客 Ubuntu18.04下安裝NFS詳細步驟_烏班圖安裝nfs-CSDN博客 1.安裝NFS服務&#xff1a; 服務器端&#xff1a; sudo apt install nfs-kernel-server

棧,優先級隊列,map,set

文章目錄 棧題目解析代碼 優先級隊列題解代碼 map題解代碼 set題解代碼 棧 題目解析 1.先把元素push進棧中&#xff0c;如果棧非空并且棧中的元素按順序和k相等就出棧&#xff0c;直到棧為空或者k ! sk.top() 代碼 #include<iostream> #include<stack> #include&l…

C++ Primer 類的靜態成員

歡迎閱讀我的 【CPrimer】專欄 專欄簡介&#xff1a;本專欄主要面向C初學者&#xff0c;解釋C的一些基本概念和基礎語言特性&#xff0c;涉及C標準庫的用法&#xff0c;面向對象特性&#xff0c;泛型特性高級用法。通過使用標準庫中定義的抽象設施&#xff0c;使你更加適應高級…

Java——super

在Java中&#xff0c;super關鍵字用于引用父類的成員&#xff08;屬性、方法或構造器&#xff09;。它在繼承關系中非常重要&#xff0c;主要用于以下幾種場景&#xff1a; 1. 調用父類的構造器 在子類的構造器中&#xff0c;可以使用super關鍵字調用父類的構造器。super()必須…

Unity 全局屏幕點擊特效

思路&#xff1a; 1、生成一個點擊特效實例&#xff0c;每點擊屏幕&#xff0c;就調整特效實例的位置并控制特效的顯隱狀態即可。 2、需要注意要保證在編輯器開發時或手機上運行時都要顯示點擊效果。 方案一 &#xff08;推薦&#xff09; using UnityEngine; using UnityEn…

什么是業務流程分類框架

業務流程分類框架是一個用于組織和系統化地分類業務流程的結構化方法。它旨在幫助企業理解、管理、分析和改進其運營流程。 可以把它想象成一個圖書館的圖書分類系統&#xff0c;幫助快速找到和理解不同類型的書籍。對于業務流程來說&#xff0c;分類框架幫助快速了解不同類型的…

基于springboot校園健康系統的設計與實現(源碼+文檔)

大家好我是風歌&#xff0c;今天要和大家聊的是一款基于springboot的園健康系統的設計與實現。項目源碼以及部署相關請聯系風歌&#xff0c;文末附上聯系信息 。 項目簡介&#xff1a; 基于springboot校園健康系統的設計與實現的主要使用者管理員具有最高的權限&#xff0c;通…

【Leetcode】平衡二叉樹

平衡二叉樹 題目 思路與代碼實現 常規解法&#xff1a; int max(int a,int b){return a>b?a:b;}int maxDepth(struct TreeNode* root) {if(rootNULL)return 0;return 1max(maxDepth(root->left),maxDepth(root->right)); }bool isBalanced(struct TreeNode* root)…

【AI實踐】阿里百煉文本對話Agent安卓版搭建

環境&#xff1a;安卓手機運行環境&#xff1b;WinsurfAI編程工具&#xff1b;阿里百煉提前創建Agent應用&#xff1b; 耗時&#xff1a;2小時&#xff1b; 1&#xff0c;新建安卓項目 完成文本輸入&#xff0c;并將輸入的文字顯示出來。 2&#xff0c;安裝SDK 參考文檔 安…

一文讀懂Docker之Docker Compose

目錄 一、Docker Compose簡介 二、Docker Compose的安裝和基本使用 1、Docker Compose的安裝 步驟一、下載docker-compose 步驟二、新增可執行權限 步驟三、查看是否安裝成功 2、Docker Compose的基本使用 (1)、docker-compose up (2)、docker-compose ps (3)、docke…

WordPress“更新失敗,響應不是有效的JSON響應”問題的修復

在使用WordPress搭建網站時&#xff0c;許多人在編輯或更新文章時&#xff0c;可能會遇到一個提示框&#xff0c;顯示“更新失敗&#xff0c;響應不是有效的JSON響應”。這個提示信息對于不了解技術細節的用戶來說&#xff0c;太難懂。其實&#xff0c;這個問題并不復雜&#x…

信息學奧賽一本通 1973 【16NOIP普及組】買鉛筆 | 洛谷 P1909 [NOIP 2016 普及組] 買鉛筆

【題目鏈接】 ybt 1973 【16NOIP普及組】買鉛筆 洛谷 P1909 [NOIP 2016 普及組] 買鉛筆 【題目考點】 1. 簡單數學 2. 數組 3. 向上取整 <cmath>中有函數double ceil(double x)&#xff0c;求x向上取整的值。 如果求正整數 ? a b ? \lceil \frac{a}{b} \rceil ?…

C++中的.*運算符

看運算符重載的時候&#xff0c;看到這一句 .* :: sizeof ?: . 注意以上5個運算符不能重載。 :: sizeof ?: . 這四個好理解&#xff0c;畢竟都學過&#xff0c;但.*是什么&#xff1f; 于是自己整理了一下 .* 是一種 C 中的運算符&#xff0c;稱為指針到成…

【JavaEE進階】MyBatis通過注解實現增刪改查

目錄 &#x1f343;前言 &#x1f340;打印日志 &#x1f334;傳遞參數 &#x1f38b;增(Insert) &#x1f6a9;返回主鍵 &#x1f384;刪(Delete) &#x1f332;改(Update) &#x1f333;查(Select) &#x1f6a9;起別名 &#x1f6a9;結果映射 &#x1f6a9;開啟駝…

【分布式理論14】分布式數據庫存儲:分表分庫、主從復制與數據擴容策略

文章目錄 一、分表分庫1. 數據分表的必要性與方式2. 數據分庫原則與優勢 二、主從復制1. 讀寫分離架構設計2. 數據復制方式3. MySQL實現主從復制4. MySQL主從復制實踐與高可用方案 三、數據擴容 隨著業務的不斷發展和數據量的增長&#xff0c;傳統的單機關系型數據庫已經逐漸不…