Linux:LCD驱动开发
目录
1.不同接口的LCD硬件操作原理
应用工程师眼中看到的LCD
1.1像素的颜色怎么表示
编辑 1.2怎么把颜色发给LCD
驱动工程师眼中看到的LCD
统一的LCD硬件模型
8080接口
TFTRGB接口
什么是MIPI
Framebuffer驱动程序框架
怎么编写Framebuffer驱动框架
硬件LCD时序分析
8080接口LCD
TFTRGB接口LCD
IMX6ULL中的LCD控制器
一、LCD接口概述
二、external Signal
三、时钟
四、功能描述
单buffer和双biffer
使用双buffer
1.不同接口的LCD硬件操作原理
应用工程师眼中看到的LCD
LCD由一个一个像素组成:每行由xres个像素,有yres行,他的分辨率是:xres*yres.
只要我们能控制任意一个像素的颜色,就可以在LCD上绘制图片,文字
1.1像素的颜色怎么表示
用红绿蓝三种颜色来表示,可以用24位数据来表示红绿蓝,也可以用16位等等格式。比如:
- bpp : bits per pixel ,每个像素用多少位来表示
- 24bpp:实际上会用到32位,其中8位未使用,其余24位中分别用8位来表示红(R),绿(G),蓝(B)
- 16bpp:有rbg565,rbg555
- rbg565:用5位表示红,用6位表示绿,用5位表示蓝
- rbg555:16位数据中用5位表示红,5位表示绿,5位表示蓝,浪费一位
1.2怎么把颜色发给LCD
假设每个像素的颜色用16位来表示,那么一个LCD的所有像素点假设有xres*yres个,
需要的内存为:xres * yres *16/8 ,也就是要设置所有像素的颜色,需要这么大的内存
这块内存就被称为framebuffer:
- Framebuffer中每块数据对应一个像素
- 每块数据的大小可能是16位,32位,这跟LCD上的像素的颜色格式有关
- 设置好LCD硬件后,只需要把颜色数据写入到Framebuffer即可

驱动工程师眼中看到的LCD
驱动工程师对LCD的理解要深入硬件,必须要回答这几个问题:
- Framebuffer在哪里
- 谁把Framebuffer中的数据发给LCD
统一的LCD硬件模型

第一种情况:将显存,LCD控制器,LCD屏幕组成一个模组(LCM)
第二种情况:将LCD控制器,显存与LCD屏幕分隔开,LCD控制器是位于ARM芯片内部的,ARM 芯片外接内存,从内存中分配出一块空间供显存使用
第一种情况一般用于单片机MCU(F103):这种接口称为8080
第二种情况一般用于能运行Linux的高性能的芯片MPU:这种接口一般被称为TFTRGB接口
这两种接口是不一样的,但整个模块的原理是一样的
8080接口
用这种接口的单片机一般性能比较弱, 所以外接的模块用内存的接口最好,我们在访问内存时,一般用数据线访问(读信号,写信号,地址线,数据线,片选信号),这样的话需要的IO口太多了,如何进行精简呢?数据线不可少,所以只能精简地址线,可以通过将地址信号转换为数据通过数据线发送,但是怎么分辨发送的是数据还是地址呢,通过引出一个引脚来分辨(data/cmd)
这种显存在屏幕上,显存一般是SRAM,它比较贵,所以一般的 8080屏幕分辨率不高
要使用更高分辨率的屏幕,就可以用以下接口的方式,这种方式内存接口比较便宜
TFTRGB接口
LCD控制器在ARM芯片内部,它会自动获取Framebuffer中的数据,那它怎么将数据发送到LCD屏幕上边呢:
1.移动像素:DCLK
2.从最后跳到下一行:HSYNC(每来一个脉冲就执行一次)
3.跳回一帧的开始(从最后一个像素段跳到第一个像素点):VSYNC
4.数据来源:RGB三组线(24条线)
5.当数据从最后跳到下一行和从会后一个像素点跳到第一个像素点的时候数据是无效的,所以使用:DE(来决定数据是否有效)
什么是MIPI
实际上上边这两种接口的实质是一样的,这两种接口都可以归入一个标准:MIPI标准
MIPI表示“Mobile Industry Proc8080essor Interface”,即移动产业处理器接口,是MIPI联盟发起的为移动应用处理器制定的开放标准和一个规范。主要是手机内部的接口(摄像头,显示器接口,射频/基带接口)等标准化,从而减少手机内部接口的复杂程度及增加设计的灵活性
对于LCD,MIPI可以分为3类:
MIPI-DBI(Display Bus Interface)
既可以是Bus(总线),就是既能发送命令,常用的8080接口就是属于DBI接口
MIPI-DPI(Display Pixel Interface)
Pixel(像素),强调的是操作单个像素,在MPU上的LCD控制器就是这种接口
MIPI-DSI(Display Serial Interface)
Serial,相比于DBI,DPI需要使用很多接口线,DSI需要的接口线大为减少
Framebuffer驱动程序框架
它再怎么复杂,还是一个字符驱动程序
LCD驱动程序分为
1.上层比较通用性的代码(框架):fbmem.c
2.硬件驱动:对于不同的芯片还有不同的硬件相关的文件:s3c2410fb.c STM32MP157_fb.c
调用关系:
示例1:
app: open("/dev/fb0", ...) 主设备号:29 , 次设备号: 0
---------------------------------------------------------------------------
kernel:fb_openint fbidx = iminor(inode);struct fb_info *info = = registered_fb[0];示例2:
app: read()
----------------------------------------------------------------------------
kernel:fb_readint fbidx = iminor(inode);struct fb_info *info = registered_fb[fbidx];if(info -> fbops -> fb_read)return info -> fbops -> fb_read(info, buf count ppos);src = (u32 __inomem *) (info -> screen_base + p);dst = buffer;*dst++ == fb_readl(src++);copy_to_user(buf, buffer, c);
怎么编写Framebuffer驱动框架
核心:
struct fb_info {atomic_t count;int node;int flags;struct mutex lock; /* Lock for open/release/ioctl funcs */struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */struct fb_var_screeninfo var; /* Current var */struct fb_fix_screeninfo fix; /* Current fix */struct fb_monspecs monspecs; /* Current Monitor specs */struct work_struct queue; /* Framebuffer event queue */struct fb_pixmap pixmap; /* Image hardware mapper */struct fb_pixmap sprite; /* Cursor hardware mapper */struct fb_cmap cmap; /* Current cmap */struct list_head modelist; /* mode list */struct fb_videomode *mode; /* current mode */#ifdef CONFIG_FB_BACKLIGHT/* assigned backlight device *//* set before framebuffer registration, remove after unregister */struct backlight_device *bl_dev;/* Backlight level curve */struct mutex bl_curve_mutex; u8 bl_curve[FB_BACKLIGHT_LEVELS];
#endif
#ifdef CONFIG_FB_DEFERRED_IOstruct delayed_work deferred_work;struct fb_deferred_io *fbdefio;
#endifstruct fb_ops *fbops;struct device *device; /* This is the parent */struct device *dev; /* This is this fb device */int class_flag; /* private sysfs flags */
#ifdef CONFIG_FB_TILEBLITTINGstruct fb_tile_ops *tileops; /* Tile Blitting */
#endifunion {char __iomem *screen_base; /* Virtual address */char *screen_buffer;};unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */ void *pseudo_palette; /* Fake palette of 16 colors */
#define FBINFO_STATE_RUNNING 0
#define FBINFO_STATE_SUSPENDED 1u32 state; /* Hardware state i.e suspend */void *fbcon_par; /* fbcon use-only private area *//* From here on everything is device dependent */void *par;/* we need the PCI or similar aperture base/size notsmem_start/size as smem_start may just be an objectallocated inside the aperture so may not actually overlap */struct apertures_struct {unsigned int count;struct aperture {resource_size_t base;resource_size_t size;} ranges[0];} *apertures;bool skip_vt_switch; /* no VT switch on suspend/resume required */
};
1.分配fb_info:framebuffer_alloc
2.设置fb_info:var , fbops ,硬件相关操作
3.注册fb_info:register_framebuffer
4.进行硬件相关的操作
代码如下:
#include <linux/module.h>#include <linux/compat.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/vt.h>
#include <linux/init.h>
#include <linux/linux_logo.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/console.h>
#include <linux/kmod.h>
#include <linux/err.h>
#include <linux/device.h>
#include <linux/efi.h>
#include <linux/fb.h>#include <asm/fb.h>static strcut fb_info *myfb_info;static struct fb_ops myfb_ops = {.owner = THIS_MODULE,.fb_fillrect = cfb_fillrect,.fb_copyarea = cfb_copyarea,.fb_imageblit = cfb_imageblit,
};/*入口函数*/
static int __init lcd_drv_init(void)
{dma_addr_t phy_addr;/*分配fb_info*/myfb_info = framebuffer_alloc(0,NULL);/*设置fb_info*//*1.var: LCD的分辨率,颜色格式等*/myfb_info -> var.xres = 1024;myfb_info -> var.yres = 600;myfb_info -> var.bits_per_pixel = 16;myfb_info -> var.red.offset = 11;myfb_info -> var.red.length = 5;myfb_info -> var.green.offset = 5;myfb_info -> var.green.length = 6;myfb_info -> var.blue.offset = 0;myfb_info -> var.blue.length = 5;/*2.fix*/myfb_info -> fiX.smem_len = myfb_info -> var.xres * myfb_info -> var.yres * 4;if(myfb_info ->var.bits_per_pixel == 24){myfb_inco -> fix.smem_len = myfb_info -> var.xres * myfb_info -> var.yres * myfb_info -> var.bits_per_pixel / 8}//framebuffer的虚拟地址myfb_info -> screen_base = dma_alloc_wc(NULL,myfb_info -> fix.smem_len, &phy_addr, GFP_KERNEL);myfb_info -> fix.smem_start = phy_addr; //framebuffer的物理地址myfb_info -> fix.type = FB_TYPE_PACKED_PIXELS;myfb_info -> fix.visual = FB_VISUAL_TRUECOLOR;/*3.fbops*/myfb_info->fbops = &myfb_ops;/*注册fb_info*/register_framebuffer(myfb_info);/*硬件操作*/return 0;
}/*出口函数*/
static void __exit lcd_drv_exit(void)
{/*反过来操作*//*反注册fb_info*/unregister_framebuffer(myfb_info);/*释放fb_info*/framebuffer_release(myfb_info);}module_init(lcd_drv_init);
module_exit(lcd_drv_exit);
MODULE_AUTHOR("zt");
MODULE_DESCRIPTION("Framebuffer driver for the linux");
MODULE_LICENSE("GPL");
对于硬件相关的操作:
这里使用QEMU中简单的四个寄存器
struct lcd_regs{
volatile unsigned int fb_base_phys; //这个寄存器存放的是显存的物理地址
volatile unsigned int fb_xres; //这个寄存器存放的是X像素
volatile unsigned int fb_yres; //这个寄存器存放的是Y像素
volatile unsigned int fb_bpp; //这个寄存器存放的是颜色的位数
};static struct lcd_regs *mylcd_regs;
/*硬件操作*/
//因为驱动不能直接操作物理地址所以需要将物理地址映射为虚拟地址
mylcd_regs = ioremap(0x021C8000,sizeof(struct lcd_regs));
//地址寄存器存放的是之前myfb_info分配的物理地址(也就是显存的物理地址)
mylcd_regs->fb_base_phys = phy_addr;
mylcd_regs->fb_xres = 500;
mylcd_regs->fb_yres = 300;
mylcd_regs->fb_bpp = 16;
硬件LCD时序分析
8080接口LCD
8080接口其实就是一般的内存接口
显存,LCD控制器,LCD屏幕放在是一块的(LCM)
1.接口原理图
数据线,读信号,写信号,地址/数据引脚(当这个引脚为高电平时,传输的为数据,为低电平时,传输的是地址),片选引脚(在Linux中内存空间都是分开的,当使用其中一段内存空间的时候,对应的片选引脚会自动有效)

当位于第一块内存区间时,片选7自动有效,当位于第二块内存区间时,片选6自动有效
其引脚图如下:
TFTRGB接口LCD


IMX6ULL中的LCD控制器
下面只是简单介绍一下,具体请看这篇文章:LCD控制器
它是TFTRGB的接口,显存和LCD控制器在IMX6Ull中所以主要就是LCD控制器与LCD屏幕进行互动
一、LCD接口概述
IMX6ULL的控制器名称为eLCDIF(增强型LCD接口)主要特性如下:
1.支持MPU模式:有些显示屏自带显存,只需要把命令、数据发送给显示屏就可以
2.支持DOTCLK模式:RGB接口,本板子就是此模式
3.VSYNC模式:针对高速数据传输(行场信号)
4.支持ITU-R BT.656接口,可以把4:2:2YcbCr格式的数据转换为模拟电视信号
5.8/16/18/24/32 bit的bpp数据都支持,取决于IO的复用设置及寄存器配置
6.MPU模式,VSYNC模式,DOTCLK模式,都可以配置时序参数
二、external Signal

三、时钟

LCD控制器有两个时钟域:外设总线时钟域,LCD像素时钟域。前者是用来让LCD控制器来正常工作,后者是用来控制电子枪移动
四、功能描述

我们在内存中划出一块内存,称之为显存,软件把数据写入到显存中
设置好LCD控制器之后,它会通过AXI总线协议从显存把RGB数据读入FIFO,再到达LCD接口(LCD Interface)。上图的Read_Data操作,在MPU模式下才用到。
单buffer和双biffer
首先要知道为什么要区分出单Buffer和双buffer
因为在IMX6ULL中,显存和LCD控制器都是在屏幕外的,当使用单buffer时,因为应用层和LCD控制器都是操作的一块显存(framebuffer),如果应用层写入数据时过快,LCD控制器还没有将显存中的数据写到屏幕中,显存有刷新了,此时就会出现问题。
使用双buffer甚至是多buffer可以有效的解决这个问题,因为应用层和LCD控制器操作的不是同一块显存,设有显存1和显存2(这里是在驱动层直接分配了两个显存大小的内存空间{实际上在IMX6ULL中是直接分配了32Mb的内存空间,相当于13个显存,是非常豪横的!!!}),刚开始应用层先写显存1,LCD控制器读显存2的数据,再一次LCD控制器读显存1的数据,应用层向显存2写数据,这样往复操作,就不会出现单buffer时的情况
使用双buffer
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <time.h>static int fd_fb;
static struct fb_fix_screeninfo fix; /* Current fix */
static struct fb_var_screeninfo var; /* Current var */
static int screen_size;
static unsigned char *fb_base;
static unsigned int line_width;
static unsigned int pixel_width;/*********************************************************************** 函数名称: lcd_put_pixel* 功能描述: 在LCD指定位置上输出指定颜色(描点),一个像素一个像素的放* 输入参数: x坐标,y坐标,颜色* 输出参数: 无* 返 回 值: 会* 修改日期 版本号 修改人 修改内容* -----------------------------------------------* 2020/05/12 V1.0 zh(angenao) 创建***********************************************************************/
void lcd_put_pixel(void *fb_base, int x, int y, unsigned int color)
{//unsigned char *pen_8 = fb_base+y*line_width+x*pixel_width;unsigned short *pen_16; unsigned int *pen_32; unsigned int red, green, blue; pen_16 = (unsigned short *)pen_8;pen_32 = (unsigned int *)pen_8;switch (var.bits_per_pixel){case 8:{*pen_8 = color;break;}case 16:{/* 565 */red = (color >> 16) & 0xff;green = (color >> 8) & 0xff;blue = (color >> 0) & 0xff;color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);*pen_16 = color;break;}case 32:{*pen_32 = color;break;}default:{printf("can't surport %dbpp\n", var.bits_per_pixel);break;}}
}void lcd_draw_screen(void *fb_base, unsigned int color)
{int x, y;for (x = 0; x < var.xres; x++)for (y = 0; y < var.yres; y++)lcd_put_pixel(fb_base, x, y, color);
}/* ./multi_framebuffer_test single* ./multi_framebuffer_test double*/
int main(int argc, char **argv)
{int i;int ret;//这个参数是记录的int nBuffers;int nNextBuffer = 1;char *pNextBuffer;unsigned int colors[] = {0x00FF0000, 0x0000FF00, 0x000000FF, 0, 0x00FFFFFF}; /* 0x00RRGGBB */struct timespec time;time.tv_sec = 0;time.tv_nsec = 100000000;if (argc != 2){printf("Usage : %s <single|double>\n", argv[0]);return -1;}fd_fb = open("/dev/fb0", O_RDWR);if (fd_fb < 0){printf("can't open /dev/fb0\n");return -1;}if (ioctl(fd_fb, FBIOGET_FSCREENINFO, &fix)){printf("can't get fix\n");return -1;}if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var)){printf("can't get var\n");return -1;}line_width = var.xres * var.bits_per_pixel / 8;pixel_width = var.bits_per_pixel / 8;screen_size = var.xres * var.yres * var.bits_per_pixel / 8;nBuffers = fix.smem_len / screen_size;printf("nBuffers = %d\n", nBuffers);fb_base = (unsigned char *)mmap(NULL , fix.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);if (fb_base == (unsigned char *)-1){printf("can't mmap\n");return -1;}if ((argv[1][0] == 's') || (nBuffers == 1)){while (1){/* use single buffer */for (i = 0; i < sizeof(colors)/sizeof(colors[0]); i++){lcd_draw_screen(fb_base, colors[i]);nanosleep(&time, NULL);}}}else{/* use double buffer *//* a. enable use multi buffers */var.yres_virtual = nBuffers * var.yres;ioctl(fd_fb, FBIOPUT_VSCREENINFO, &var);while (1){for (i = 0; i < sizeof(colors)/sizeof(colors[0]); i++){/* get buffer */pNextBuffer = fb_base + nNextBuffer * screen_size;/* set buffer */lcd_draw_screen(pNextBuffer, colors[i]);/* switch buffer */var.yoffset = nNextBuffer * var.yres;ioctl(fd_fb, FBIOPAN_DISPLAY, &var);ret = 0;ioctl(fd_fb, FBIO_WAITFORVSYNC, &ret);nNextBuffer = !nNextBuffer;nanosleep(&time, NULL);}}}munmap(fb_base , screen_size);close(fd_fb);return 0;
}
当输入single时使用单buffer,当输入double时使用双buffer,经过对比会发现明显的差异,使用双buffer的刷屏会更加流畅,并且不会出现颜色覆盖的情况。
相关文章:
Linux:LCD驱动开发
目录 1.不同接口的LCD硬件操作原理 应用工程师眼中看到的LCD 1.1像素的颜色怎么表示 编辑 1.2怎么把颜色发给LCD 驱动工程师眼中看到的LCD 统一的LCD硬件模型 8080接口 TFTRGB接口 什么是MIPI Framebuffer驱动程序框架 怎么编写Framebuffer驱动框架 硬件LCD时序分析…...
QT:常用类与组件
1.设计QQ的界面 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPushButton> #include <QLineEdit> #include <QLabel>//自定义类Widget,采用public方式继承QWidget,该类封装了图形化界面的相关操作ÿ…...
企业内训|提示词工程师高阶技术内训-某运营商研发团队
近日,TsingtaoAI为某运营商技术团队交付提示词工程师高级技术培训,本课程为期2天,深入探讨深度学习与大模型技术在提示词生成与优化、客服大模型产品设计等业务场景中的应用。内容涵盖了深度学习前沿理论、大模型技术架构设计与优化、以及如何…...
K8S真正删除pod
假设k8s的某个命名空间如(default)有一个运行nginx 的pod,而这个pod是以kubectl run pod命令运行的 1.错误示范: kubectl delete pod nginx-2756690723-hllbp 结果显示这个pod 是删除了,但k8s很快自动创建新的pod,但是…...
数据结构:队列及其应用
队列(Queue)是一种特殊的线性表,它的主要特点是先进先出(First In First Out,FIFO)。队列只允许在一端(队尾)进行插入操作,而在另一端(队头)进行删…...
26个用好AI大模型的提示词技巧
如果你已深入探索过ChatGPT、Microsoft Copilot、风变AI等前沿的生成式AI工具,那么你对“prompt”(提示词)这一核心概念一定有自己的认知。 作为连接你与AI创意源泉的桥梁,“prompt”不仅是触发无限想象的钥匙,更是塑…...
线性表二——栈stack
第一题 #include<bits/stdc.h> using namespace std; stack<char> s; int n; string ced;//如何匹配 出现的右括号转换成同类型的左括号,方便我们直接和栈顶元素 char cheak(char c){if(c)) return (;if(c]) return [;if(c}) return {;return \0;/…...
浏览器发送请求后关闭,服务器的处理过程
之前在开发中,有些后端服务处理非常慢,页面可能会出现504 Gateway time-out的提示,或者服务器还没返回数据,浏览器就关掉了。我们只是看到了浏览器关掉,但是服务器和客户端的状态都是什么样的呢? 问题 在…...
tee命令:轻松同步输出到屏幕与文件
一、命令简介 tee 命令在 Linux 和 Unix 系统中用于读取标准输入的数据,并将其同时输出到标准输出和文件中。简单来说,tee 命令可以用来分割数据流,使其既能够被输出到屏幕,也能够被写入到文件中。 二、命令参数…...
【经验技巧】如何做好S参数的仿测一致性
根据个人经验,想要做好电路板S参数的仿测一致性,如下的相关信息必须被认真对待: 1. PCB叠构(Stack up),仿真模型需要保证设计参数与板厂供应商的生产参数完全一样,这些参数包括: 叠层结构数据;介电常数;损耗因子;蚀刻因子;表面粗糙度。 2. 仿真中,需要保证信号测试…...
js逆向——webpack实战案例(一)
今日受害者网站:https://www.iciba.com/translate?typetext 首先通过跟栈的方法找到加密位置 我们跟进u函数,发现是通过webpack加载的 向上寻找u的加载位置,然后打上断点,刷新网页,让程序断在加载函数的位置 u r.n…...
Spring Boot 进阶-Spring Boot的全局异常处理机制详解
我们知道在软件运行的过程中,总会出现各种各样的问题,各种各样的异常,而程序员的主要任务之一就是解决在程序运行过程中出现的这些异常。在很多程序员开发的代码中我们会看到在关键的地方为了保证程序能够有一个正常的反馈,大量地使用了try catch finally语句。 大量的try …...
滚雪球学MySQL[7.1讲]:安全管理
全文目录: 前言7. 安全管理7.1 用户与权限管理7.1.1 创建和管理用户7.1.2 权限分配与管理7.1.3 最小权限原则 7.2 安全策略配置7.2.1 使用加密连接7.2.2 强密码策略7.2.3 定期审计和日志管理 7.3 SQL注入防范7.3.1 使用预处理语句7.3.2 输入验证与清理7.3.3 最小化数…...
反射及其应用---->2
目录 1.使用类对象 1.1创建对象 1.2使用对象属性 1.3使用方法 2.反射操作数组 3.反射获得泛型 4.类加载器 4.1双亲委派机制 4.2自定义加载器 1.使用类对象 通过反射使用类对象,主要体现3个部分 创建对象,调用方法,调用属性ÿ…...
[Python学习日记-32] Python 中的函数的返回值与作用域
[Python学习日记-32] Python 中的函数的返回值与作用域 简介 返回值 作用域 简介 在函数的介绍中我们提到了函数的返回值,当时只是做了简单的介绍,下面我们将会进行详细的介绍和演示,同时也会讲一下 Python 中的作用域,作用域分…...
儿童发光耳勺值得买吗?儿童发光耳勺最建议买的五个牌子!
儿童耳部清洁需谨慎,发光耳勺能在光线不足时提供照明,便于看清耳道。但不同产品质量参差不齐,选择时需综合考虑安全性、实用性等因素,为孩子的耳部健康做出正确选择! 这里给大家总结了全新的儿童发光耳勺的避雷指南&am…...
TIPS 二进制程序暴露符号给动态链接库使用
背景 在支持插件/扩展的C/C系统中,通常会支持在程序运行时加载动态链接库。这时二进制程序会提供一些函数/接口让动态链接库调用,但是这些函数在二进制程序中又不会使用,导致在编译时编译器直接把这些符号删除了,加载链接库就会由…...
【分布式微服务云原生】8分钟掌握微服务通信的艺术:Dubbo与OpenFeign全面解析
摘要: 在构建微服务架构时,服务间的通信机制是核心要素之一。Dubbo和OpenFeign是两个非常流行的服务调用框架,它们各有千秋,适用于不同的场景。本文将深入探讨Dubbo和OpenFeign的主要特点、使用场景以及它们之间的差异,…...
sicp每日一题[2.33]
Exercise 2.33 Fill in the missing expressions to complete the following definitions of some basic list-manipulation operations as accumulations: ; p 表示一个函数,sequence 表示一个列表 ; 这个函数将对列表中每一个元素进行 p 操作 (define (map p sequ…...
【Mybatis】常见面试题汇总 共56题
文章目录 1. 介绍下MyBatis?2. MyBatis 框架的应用场景?3. MyBatis 有哪些优点?4. MyBatis 有哪些缺点?5. MyBatis 用到了哪些设计模式?6. MyBatis常用注解有哪些?7. MyBatis 有哪些核心组件?8. MyBatis编程步骤是什么样的?9. MyBatis 和…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
