Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
linux驱动程序运行在什么空间_创想鸟

linux驱动程序运行在什么空间

linux驱动程序运行在“内核”空间。一般情况下驱动程序中都是调用kmalloc()来给数据结构分配内存,调用vmalloc()为活动的交换区分配数据结构,为某些I/O驱动程序分配缓冲区,或为模块分配空间;kmalloc和vmalloc分配的是内核的内存。

linux驱动程序运行在什么空间

本教程操作环境:linux7.3系统、Dell G3电脑。

linux驱动程序运行在“内核”空间。

对于一般编写的单片机程序来说应用程序和驱动程序往往是杂糅的,拥有一定能力水平的单片机程序编程人员可以实现应用和驱动的分层。而在Linux系统中已经强制将应用和驱动进行了分层。

在单片机程序中,应用可以直接操作底层的寄存器。而在Linux系统中却禁止这样的行为,举个例子:Linux应用的编写人员故意在应用中调用了驱动中关于电源管理的驱动,关闭了系统,那不就得不偿失了?

具体的Linux应用程序对驱动的调用如图所示:

1.png

应用程序运行在用户空间,驱动程序运行在内核空间。处于用户空间应用程序如果想要实现对内核的操作,必须经过一种”系统调用”的方法,实现从用户空间进入内核空间,实现对底层的操作。

Linux中的内核空间

内核也是程序,也应该具有自己的虚存空间,但是作为一种为用户程序服务的程序,内核空间有它自己的特点。

内核空间与用户空间的关系

在一个32位系统中,一个程序的虚拟空间最大可以是4GB,那么最直接的做法就是,把内核也看作是一个程序,使它和其他程序一样也具有4GB空间。但是这种做法会使系统不断的切换用户程序的页表和内核页表,以致影响计算机的效率。解决这个问题的最好做法就是把4GB空间分成两个部分:一部分为用户空间,另一部分为内核空间,这样就可以保证内核空间固定不变,而当程序切换时,改变的仅是程序的页表。这种做法的唯一缺点便是内核空间和用户空间均变小了。

例如:在i386这种32位的硬件平台上,Linux在文件page.h中定义了一个常量PAGE_OFFSET:

#ifdef CONFIG_MMU#define __PAGE_OFFSET  (0xC0000000)        //0xC0000000为3GB#else#define __PAGE_OFFSET  (0x00000000)#endif#define PAGE_OFFSET((unsigned long)__PAGE_OFFSET)

Linux以PAGE_OFFSET为界将4GB的虚拟内存空间分成了两部分:地址0~3G-1这段低地址空间为用户空间,大小为3GB;地址3GB~4GB-1这段高地址空间为内核空间,大小为1GB。

当系统中运行多个程序时,多个用户空间与内核空间的关系可以表示如下图:

1.png

如图中所示,程序1、2……n共享内核空间。当然,这里的共享指得是分时共享,因为在任何时刻,对于单核处理器系统来说,只能有一个程序在运行。

内核空间的总体布局

Linux在发展过程中,随着硬件设备的更新和技术水平的提高,其内核空间布局的发展也是一种不断打补丁的方式。这样的后果就是使得内核空间被分成不同的几个区域,而且在不同的区域具有不同的映射方式。通常,人们认为Linux内核空间有三个区域,即DMA区(ZONE_DMA)、普通区(ZONE_NORMAL)和高端内存区(ZONE_HIGHMEM)。

实际物理内存较小时内核空间的直接映射

早期计算机实际配置的物理内存通常只有几MB,所以为了提高内核通过虚拟地址访问物理地址内存的速度,内核空间的虚拟地址与物理内存地址采用了一种从低地址向高地址依次一一对应的固定映射方式,如下图所示:

2.png

可以看到,这种固定映射方式使得虚拟地址与物理地址的关系变得很简单,即内核虚拟地址与实际物理地址只在数值上相差一个固定的偏移量PAGE_OFFSET,所以当内核使用虚拟地址访问物理页框时,只需在虚拟地址上减去PAGE_OFFSET即可得到实际物理地址,比使用页表的方式要快得多!

由于这种做法几乎就是直接使用物理地址,所以这种按固定映射方式的内核空间也就叫做“物理内存空间”,简称物理内存。另外,由于固定映射方式是一种线性映射,所以这个区域也叫做线性映射区。

当然,这种情况下(计算机实际物理内存较小时),内核固定映射空间仅占整个1GB内核空间的一部分。例如:在配置32MB实际物理内存的x86计算机系统时,内核的固定映射区便是PAGE_OFFSET~(PAGE_OFFSET+0x02000000)这个32MB空间。那么内核空间剩余的内核虚拟空间怎么办呢?

当然还是按照普通虚拟空间的管理方式,以页表的非线性映射方式使用物理内存。具体来说,在整个1GB内核空间中去除固定映射区,然后在剩余部分中再去除其开头部分的一个8MB隔离区,余下的就是映射方式与用户空间相同的普通虚拟内存映射区。在这个区,虚拟地址和物理地址不仅不存在固定映射关系,而且通过调用内核函数vmalloc()获得动态内存,故这个区就被称为vmalloc分配区,如下图所示:

3.png

对于配置32MB实际物理内存的x86计算机系统来说,vmalloc分配区的起始位置为PAGE_OFFSET+0x02000000+0x00800000。

这里说明一下:这里说的内核空间与物理页框的固定映射,实质上是内核页对物理页框的一种“预定”,并不是说这些页就“霸占”了这些物理页框。即只有当虚拟页真正需要访问物理页框时,虚拟页才与物理页框绑定。而平时,当某个物理页框不被与它对应的虚拟页所使用时,该页框完全可以被用户空间以及后面所介绍的内核kmalloc分配区使用。

总之,在实际物理内存较小的系统中,实际内存的大小就是内核空间的物理内存区与vmalloc分配区的边界。

ZONE_DMA区与ZONE_NORMAL区

对于整个1GB的内核空间,人们还把该空间头部的16MB叫做DMA区,即ZONE_DMA区,因为以往硬件将DMA空间固定在了物理内存的低16MB空间;其余区则叫做普通区,即ZONE_NORMAL。

内核空间的高端内存

随着计算机技术的发展,计算机的实际物理内存越来越大,从而使得内核固定映射区(线性区)也越来越大。显然,如果不加以限制,当实际物理内存达到1GB时,vmalloc分配区(非线性区)将不复存在。于是以前开发的、调用了vmalloc()的内核代码也就不再可用,显然为了兼容早期的内核代码,这是不能允许的。

下图就表示了这种内核空间所面临的局面:

4.png

显然,出现上述问题的原因就是没有预料到实际物理内存可以超过1GB,因而没有为内核固定映射区的边界设定限制,而任由其随着实际物理内存的增大而增大。

解决上述问题的方法就是:对内核空间固定映射区的上限加以限制,使之不能随着物理内存的增加而任意增加。Linux规定,内核映射区的上边界的值最大不能大于一个小于1G的常数high_menory,当实际物理内存较大时,以3G+high_memory为边界来确定物理内存区。

例如:对于x86系统,high_memory的值为896M,于是1GB内核空间余下的128MB为非线性映射区。这样就确保在任何情况下,内核都有足够的非线性映射区以兼容早期代码并可以按普通虚存方式访问实际物理内存的1GB以上的空间。

也就是说,高端内存的最基本思想:借一段地址空间,建立临时地址映射,用完后释放,达到这段地址空间可以循环使用,访问所有物理内存。当计算机是物理内存较大时,内核空间的示意图如下:

5.png

习惯上,Linux把内核空间3G+high_memory~4G-1的这个部分叫做高端内存区(ZONE_HIGHMEM)。

总结一下:在x86结构的内核空间,三种类型的区域(从3G开始计算)如下:

ZONE_DMA:内核空间开始的16MBZONE_NORMAL:内核空间16MB~896MB(固定映射)ZONE_HIGHMEM :内核空间896MB ~ 结束(1G)

根据应用目标不同,高端内存区分vmalloc区、可持久映射区和临时映射区。内核空间中高端内存的布局如下图所示:

6.png

vmalloc映射区

vmalloc映射区时高端内存的主要部分,该区间的头部与内核线性映射空间之间有一个8MB的隔离区,尾部与后续的可持久映射区有一个4KB的隔离区。

vmalloc映射区的映射方式与用户空间完全相同,内核可以通过调用函数vmalloc()在这个区域获得内存。这个函数的功能相当于用户空间的malloc(),所提供的内存空间在虚拟地址上连续(注意,不保证物理地址连续)。

可持久内核映射区

如果是通过 alloc_page() 获得了高端内存对应的 page,如何给它找个线性空间?

内核专门为此留出一块线性空间,从PKMAP_BASE开始,用于映射高端内存,就是可持久内核映射区。

在可持久内核映射区,可通过调用函数kmap()在物理页框与内核虚拟页之间建立长期映射。这个空间通常为4MB,最多能映射1024个页框,数量较为稀少,所以为了加强页框的周转,应及时调用函数kunmap()将不再使用的物理页框释放。

临时映射区

临时映射区也叫固定映射区和保留区。该区主要应用在多处理器系统中,因为在这个区域所获得的内存空间没有所保护,故所获得的内存必须及时使用;否则一旦有新的请求,该页框上的内容就会被覆盖,所以这个区域叫做临时映射区。

关于高端内存区一篇很不错的文章:linux 用户空间与内核空间——高端内存详解。

内核内存分配修饰符gfp

为了在内核内存请求函数对请求进行必要的说明,Linux定义了多种内存分配修饰符gfp。它们是行为修饰符、区修饰符、类型修饰符。

行为修饰符

在内存分配函数中的行为修饰符说明内核应当如何分配内存。主要行为修饰符如下:

Linux的主要内核内存分配行为修饰符

修饰符说明__GFP_WAIT分配器可以休眠__GFP_HIGH分配器可以访问紧急事件缓冲池__GFP_IO分配器可以启动磁盘IO__GFP_FS分配器可以启动文件系统IO__GFP_COLD分配器应该使用高速缓冲中快要淘汰的页框__GFP_NOWARN分配器不发出警告__GFP_REPEAT分配失败时重新分配__GFP_NOFAILT分配失败时重新分配,直至成功__GFP_NORETRY分配失败时不再重新分配

区修饰符

区修饰符说明需要从内核空间的哪个区域中分配内存。内存分配器默认从内核空间的ZONE_NORMAL开始逐渐向高端获取为内存请求者分配内存区,如果用户特意需要从ZONE_DMA或ZONE_HOGNMEM获得内存,那么就需要内存请求者在内存请求函数中使用以下两个区修饰符说明:

Linux的主要内核内存分配区修饰符

修饰符说明__GFP_DMA从ZONE_DMA区分配内存__GFP_HIGHMEM从ZONE_HIGHMEM区分配内存

类型修饰符

类型修饰符实质上是上述所述修饰符的联合应用。也就是:将上述的某些行为修饰符和区修饰符,用“|”进行连接并另外取名的修饰符。这里就不多介绍了。

内核常用内存分配及地址映射函数

函数vmalloc()

函数vmalloc()在vmalloc分配区分配内存,可获得虚拟地址连续,但并不保证其物理页框连续的较大内存。与物理空间的内存分配函数malloc()有所区别,vmalloc()分配的物理页不会被交换出去。函数vmalloc()的原型如下:

void *vmalloc(unsigned long size){       return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);}
void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot){return kmalloc(size, (gfp_mask | __GFP_COMP) & ~__GFP_HIGHMEM);}

其中,参数size为所请求内存的大小,返回值为所获得内存虚拟地址指针。

与vmalloc()配套的释放函数如下:

void vfree(const void *addr){kfree(addr);}

其中,参数addr为待释放内存指针。

函数kmalloc()

kmalloc()是内核另一个常用的内核分配函数,它可以分配一段未清零的连续物理内存页,返回值为直接映射地址。由kmalloc()可分配的内存最大不能超过32页。其优点是分配速度快,缺点是不能分配大于128KB的内存页(出于跨平台考虑)。

在linux/slab.h文件中,该函数的原型声明如下:

static __always_inline void *kmalloc(size_t size, gfp_t flags){struct kmem_cache *cachep;void *ret;if (__builtin_constant_p(size)) {int i = 0;if (!size)return ZERO_SIZE_PTR;#define CACHE(x) if (size <= x) goto found; else i++;#include #undef CACHEreturn NULL;found:#ifdef CONFIG_ZONE_DMAif (flags & GFP_DMA)cachep = malloc_sizes[i].cs_dmacachep;else#endifcachep = malloc_sizes[i].cs_cachep;ret = kmem_cache_alloc_notrace(cachep, flags);trace_kmalloc(_THIS_IP_, ret,      size, slab_buffer_size(cachep), flags);return ret;}return __kmalloc(size, flags);}

其中,参数size为以字节为单位表示的所申请空间的大小;参数flags决定了所分配的内存适合什么场合。

与函数kmalloc()对应的释放函数如下:

void kfree(const void *objp){struct kmem_cache *c;unsigned long flags;trace_kfree(_RET_IP_, objp);if (unlikely(ZERO_OR_NULL_PTR(objp)))return;local_irq_save(flags);kfree_debugcheck(objp);c = virt_to_cache(objp);debug_check_no_locks_freed(objp, obj_size(c));debug_check_no_obj_freed(objp, obj_size(c));__cache_free(c, (void *)objp);local_irq_restore(flags);}

小结一下,kmalloc、vmalloc、malloc的区别:

kmalloc和vmalloc是分配的是内核的内存,malloc分配的是用户的内存;kmalloc保证分配的内存在物理上是连续的,vmalloc保证的是在虚拟地址空间上的连续,malloc不保证任何东西;kmalloc能分配的大小有限,vmalloc和malloc能分配的大小相对较大;vmalloc比kmalloc要慢。

也就是说:kmalloc、vmalloc这两个函数所分配的内存都处于内核空间,即从3GB~4GB;但位置不同,kmalloc()分配的内存处于3GB~high_memory(ZONE_DMA、ZONE_NORMAL)之间,而vmalloc()分配的内存在VMALLOC_START~4GB(ZONE_HIGHMEM)之间,也就是非连续内存区。一般情况下在驱动程序中都是调用kmalloc()来给数据结构分配内存,而vmalloc()用在为活动的交换区分配数据结构,为某些I/O驱动程序分配缓冲区,或为模块分配空间。

7.png

可参考文章:Kmalloc和Vmalloc的区别。

函数alloc_pages()

与上述在虚拟空间分配内存的函数不同,alloc_pages()是在物理内存空间分配物理页框的函数,其原型如下:

static inline struct page * alloc_pages(gfp_t gfp_mask, unsigned int order){if (unlikely(order >= MAX_ORDER))return NULL;return alloc_pages_current(gfp_mask, order);}

其中,参数order表示所分配页框的数目,该数目为2^order。order的最大值由include/Linux/Mmzone.h文件中的宏MAX_ORDER决定。参数gfp_mask为说明内存页框分配方式及使用场合。

函数返回值为页框块的第一个页框page结构的地址。

调用下列函数可以获得页框的虚拟地址:

void *page_address(struct page *page){unsigned long flags;void *ret;struct page_address_slot *pas; if (!PageHighMem(page))return lowmem_page_address(page); pas = page_slot(page);ret = NULL;spin_lock_irqsave(&pas->lock, flags);if (!list_empty(&pas->lh)) {struct page_address_map *pam; list_for_each_entry(pam, &pas->lh, list) {if (pam->page == page) {ret = pam->virtual;goto done;}}}done:spin_unlock_irqrestore(&pas->lock, flags);return ret;}

使用函数alloc_pages()获得的内存应该使用下面的函数释放:

void __free_pages(struct page *page, unsigned int order){if (put_page_testzero(page)) {if (order == 0)free_hot_page(page);else__free_pages_ok(page, order);}}

函数kmap()

kmap()是一个映射函数,它可以将一个物理页框映射到内核空间的可持久映射区。这种映射类似于内核ZONE_NORMAL的固定映射,但虚拟地址与物理地址的偏移不一定是PAGE_OFFSET。由于内核可持久映射区的容量有限(总共只有4MB),因此当内存使用完毕后,应该立即释放。

函数kmap()的函数原型如下:

void *kmap(struct page *page){might_sleep();if (!PageHighMem(page))return page_address(page);return kmap_high(page);}

小结

由于CPU的地址总线只有32位, 32的地址总线无论是从逻辑上还是从物理上都只能描述4G的地址空间(232=4Gbit),在物理上理论上最多拥有4G内存(除了IO地址空间,实际内存容量小于4G),逻辑空间也只能描述4G的线性地址空间。

为了合理的利用逻辑4G空间,Linux采用了3:1的策略,即内核占用1G的线性地址空间,用户占用3G的线性地址空间。所以用户进程的地址范围从0~3G,内核地址范围从3G~4G,也就是说,内核空间只有1G的逻辑线性地址空间。

如果Linux物理内存小于1G的空间,通常内核把物理内存与其地址空间做了线性映射,也就是一一映射,这样可以提高访问速度。但是,当Linux物理内存超过1G时,线性访问机制就不够用了,因为只能有1G的内存可以被映射,剩余的物理内存无法被内核管理,所以,为了解决这一问题,Linux把内核地址分为线性区和非线性区两部分,线性区规定最大为896M,剩下的128M为非线性区。从而,线性区映射的物理内存成为低端内存,剩下的物理内存被成为高端内存。与线性区不同,非线性区不会提前进行内存映射,而是在使用时动态映射。

低端内存又分成两部分:ZONE_DMA:内核空间开始的16MB、ZONE_NORMAL:内核空间16MB~896MB(固定映射)。剩下的就是高端内存:ZONE_HIGHMEM :内核空间896MB ~ 结束(1G)。

根据应用目标不同,高端内存区分vmalloc区、可持久映射区和临时映射区三部分。vmalloc区使用vmalloc()函数进行分配;可持久映射区使用allc_pages()获得对应的 page,在利用kmap()函数直接映射;临时映射区一般用于特殊需求。

用户空间和内核空间

内核空间(3G~4G)

高端内存(3G+high_memory~4G)ZONE_HIGHMEM

非线性映射区

临时映射区可持久映射区vmalloc区

低端内存(3G~3G+high_memory-1)

线性映射区(固定映射区)

ZONE_NORMALZONE_DMA用户空间(0~3G-1)页目录–>中间页目录–>页表

相关推荐:《Linux视频教程》

以上就是linux驱动程序运行在什么空间的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/138230.html

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
如何在共享主机(shared hosting)上克服composer的限制
上一篇 2025年11月30日 13:16:40
laravel如何实现多语言和本地化功能_Laravel多语言与本地化功能实现方法
下一篇 2025年11月30日 13:18:42

相关推荐

  • 蝴蝶号无人直播完整流程详解:搭建+开播+引流

    蝴蝶号无人直播完整流程详解:搭建+开播+引流蝴蝶号无人直播完整流程详解:搭建+开播+引流蝴蝶号无人直播完整流程详解:搭建+开播+引流蝴蝶号无人直播完整流程详解:搭建+开播+引流

    蝴蝶号无人直播的完整流程包括前期准备、直播搭建、开播设置、引流推广、监控与维护五个步骤。前期准备需完成账号注册认证、硬件设备配置、软件安装及素材准备;直播搭建涉及场景设置、素材导入、循环播放设定及自动化脚本配置;开播设置包括直播间信息填写、推流配置与测试直播;引流推广可通过平台内工具、社交媒体、内容…

    2026年9月22日 • 用户投稿
    100
  • 如何在VEED.io中制作AI视频?在线工具快速剪辑AI内容的步骤

    如何在VEED.io中制作AI视频?在线工具快速剪辑AI内容的步骤如何在VEED.io中制作AI视频?在线工具快速剪辑AI内容的步骤如何在VEED.io中制作AI视频?在线工具快速剪辑AI内容的步骤如何在VEED.io中制作AI视频?在线工具快速剪辑AI内容的步骤

    VEED.io通过“文本转视频”和“AI形象”功能,让视频制作变得简单高效。用户只需输入文本,即可生成带AI配音、字幕和匹配素材的视频,或选择AI虚拟人物进行口型同步播报。平台还提供AI语音合成、自动字幕、多语言支持及丰富编辑功能,便于后期精修。优化效果需从高质量文本入手,合理选择声音与形象,并通过…

    2026年9月22日 • 用户投稿
    000
  • Java中递归处理列表:条件性移除最大值策略与实现

    本教程深入探讨了如何在Java中使用递归方法,根据特定条件(如列表是否已排序、最大值是否位于列表的首尾)来移除列表中的最大值。文章将详细阐述如何设计一个高效的递归算法,包括排序检查、最大值定位以及条件性移除的实现细节,并提供完整的代码示例和注意事项,帮助读者掌握递归在复杂列表操作中的应用。 引言:递…

    2026年9月22日
    000
  • 玩转 Spring Boot 集成篇(定时任务框架Quartz)

    玩转 Spring Boot 集成篇(定时任务框架Quartz)玩转 Spring Boot 集成篇(定时任务框架Quartz)玩转 Spring Boot 集成篇(定时任务框架Quartz)玩转 Spring Boot 集成篇(定时任务框架Quartz)

    在日常项目研发中,定时任务可谓是必不可少的一环,关于 spring boot 如何实现静态定时任务、动态定时任务以及如何开启多线程跑任务,均已在上篇分享过,不再赘述。 虽然 Spring Boot 内置注解方式实现的定时任务,在一定程度上也能解决一定的业务场景问题,但是若做更复杂的动作,例如启停任务…

    2026年9月22日 • 用户投稿
    100
  • Cortana如何连接邮箱_Cortana邮箱同步配置方法

    首先需将邮箱账户与Cortana连接,可通过Windows设置添加账户或在Cortana应用内手动配置,支持Outlook.com、Gmail及Exchange等类型;完成账户添加后,须在隐私权限中启用邮件读取和同步权限,确保Cortana可访问邮件、日历及联系人数据,从而实现智能提醒与信息同步功能…

    2026年9月22日
    000
  • 如何用Sublime导出MySQL数据表结构_生成Markdown或HTML格式文档

    要使用 sublime text 导出 mysql 数据表结构并生成 markdown 或 html 文档,需通过以下步骤操作:1. 使用 show create table 命令或 mysqldump 工具获取建表语句;2. 在 sublime 中整理字段信息,按字段名、类型、是否为空、键、默认值…

    2026年9月22日
    000
  • 三角洲行动S6九格保险任务速通指南

    三角洲行动S6九格保险任务速通指南三角洲行动S6九格保险任务速通指南三角洲行动S6九格保险任务速通指南三角洲行动S6九格保险任务速通指南

    在《三角洲行动》s6赛季中,九格保险任务成了不少玩家头疼的难题,耗时久、节奏慢,稍不注意就被卡住。其实只要掌握策略,合理安排任务顺序,高效推进并非难事!接下来这份分阶段速通攻略,将帮你理清思路,快速通关九格保险任务! 三角洲行动S6赛季九格保险任务高效速通指南 第一阶段:聚焦主线与关键前置 优先完成…

    2026年9月22日 • 用户投稿
    100
  • 解决PHP应用中本地文件更新后网页视图不刷新的缓存问题

    本文探讨了PHP应用中,本地JSON或图片文件更新后,网页视图无法实时刷新的常见问题。核心原因在于浏览器缓存机制。文章将提供多种解决方案,包括强制刷新、隐身模式诊断、以及通过URL参数、服务器配置(.htaccess)和文件版本控制来有效管理缓存,确保用户始终获取最新数据。 理解问题:本地文件更新与…

    2026年9月22日
    200
  • VSCode如何安装和使用插件 VSCode插件管理的高效方法

    安装插件需通过vscode扩展视图搜索并点击安装,部分插件需重启或配置后生效;2. 使用插件时可通过命令面板、上下文菜单、状态栏或自动语言特性调用功能,并在设置中自定义行为;3. 高效管理应定期审视插件使用频率,禁用或卸载不常用者,关注性能影响,利用“开发者: 显示正在运行的扩展”识别资源占用高的插…

    2026年9月22日
    200
  • Java Stream API:从嵌套集合中提取唯一值的高效实践

    本文深入探讨如何利用Java Stream API,从包含嵌套集合的对象列表中高效地提取唯一的字符串值。我们将重点介绍flatMap()和mapMulti()这两种强大的流操作,演示它们如何替代传统的嵌套循环,从而实现代码的简洁性、可读性以及潜在的性能优化。 在java应用开发中,我们经常会遇到处理…

    2026年9月22日
    100
  • safari浏览器如何将网页保存为PDF_safari浏览器网页保存为PDF方法

    Safari浏览器支持将网页保存为PDF,可通过三种方式实现:1. 使用打印功能,点击“文件”→“打印”,选择“另存为PDF”并设置参数后保存;2. 点击共享按钮,选择“创建PDF”,生成后存储到指定位置;3. 利用快捷指令应用创建自动化流程,获取当前网页并转换为PDF自动归档。 如果您在浏览网页时…

    2026年9月22日
    100
  • CapCut的AI混合工具如何使用?快速制作高质量短视频的教程

    CapCut的AI混合工具通过智能算法将多段素材自然融合,支持画中画、双重曝光、背景替换等效果,提升视频创意与质感;使用时需导入素材并分层,选择“混合模式”如滤色、叠加等,结合不透明度、位置调整实现融合;可打造情绪隐喻、时间流逝等叙事效果,增强艺术表达;避免过度使用、素材冲突等问题,善用蒙版、色彩调…

    2026年9月22日
    500
  • 使用Java Selenium验证表格数据排序:金额列的升序与降序检查

    本教程详细介绍了如何利用Java Selenium WebDriver验证网页表格中金额列的排序功能。文章涵盖了从环境配置、登录应用到数据提取、清洗、数值转换,再到实现表格数据(特别是金额数据)的升序或降序验证的完整流程。通过示例代码,演示了如何获取页面元素、处理文本数据,并使用JUnit进行断言,…

    2026年9月22日
    100
  • VSCode安装C/C++代码格式化 专业VSCode开发环境配置

    配置VSCode进行C/C++开发需安装C/C++扩展包和clang-format,设置自动格式化与调试环境,推荐使用CMake Tools、Include Autocomplete等扩展,结合快捷键、代码片段和任务自动化提升效率。 配置VSCode以实现C/C++代码的专业格式化和高效开发环境,核…

    2026年9月22日
    400
  • 抖音播放量是什么意思?抖音播放量如何变现呢

    短视频平台已成为当下最受欢迎的传播媒介之一。作为国内领先的短视频平台,抖音凭借其强大的算法推荐机制和丰富的内容生态,吸引了大量用户。而抖音播放量,作为衡量短视频传播效果的重要指标,也逐渐成为创作者和品牌方关注的重点。本文将深入解析抖音播放量的含义,探讨其背后的逻辑及影响因素,为短视频内容生产者提供有…

    2026年9月22日
    000
  • Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE)

    could not find doxygen (missing: doxygen_executable)  使用cmake .. 有时候会遇到如下问题: 代码语言:javascript代码运行次数:0运行复制 $ cmake ..– The CXX compiler identification …

    2026年9月22日
    100
  • Laravel 8 登录后重定向到仪表盘:完整教程

    本教程详细阐述了在 Laravel 8 中实现用户登录后重定向到仪表盘的多种方法。我们将探讨 Laravel 默认的重定向机制、如何正确配置仪表盘路由及其中间件,并提供通过自定义 LoginController 实现精确重定向的示例代码。通过本文,您将全面掌握 Laravel 认证后的重定向流程,并…

    2026年9月22日
    500
  • Ubuntu VMware Tools安装详细过程(非常靠谱)「建议收藏」

    Ubuntu VMware Tools安装详细过程(非常靠谱)「建议收藏」Ubuntu VMware Tools安装详细过程(非常靠谱)「建议收藏」Ubuntu VMware Tools安装详细过程(非常靠谱)「建议收藏」Ubuntu VMware Tools安装详细过程(非常靠谱)「建议收藏」

    大家好,很高兴再次与大家见面,我是你们的朋友全栈君。 说明:这篇博客是博主亲自编写的,内容独特,辛苦付出,请大家尊重原创,感谢支持! 一.前言VMware Ubuntu安装的详细指南:https://www.php.cn/link/35e7132c1742eaa9dacfedd5607b5f94。 …

    2026年9月22日 • 用户投稿
    900
  • VSCode如何集成Jai游戏开发环境 VSCode配置高性能游戏编程工作流

    配置#%#$#%@%@%$#%$#%#%#$%@_e2fc++805085e25c9761616c00e065bfe8集成jai游戏开发环境的核心在于正确设置编译器与调试器并利用扩展提升效率,1. 配置settings.json指定jai.compilerpath、builddirectory、in…

    2026年9月22日
    500
  • 决战江城之巅 掠夺者PL Girls引爆打瓦热潮!

    决战江城之巅 掠夺者PL Girls引爆打瓦热潮!决战江城之巅 掠夺者PL Girls引爆打瓦热潮!决战江城之巅 掠夺者PL Girls引爆打瓦热潮!决战江城之巅 掠夺者PL Girls引爆打瓦热潮!

    10月12日,plgirls掠夺者校园电竞女神联赛【线下城市晋级赛-武汉站】在武汉世界城光谷学生街圆满落幕。经过紧张激烈的对抗,「dcg」与「jmm」两支战队从四强中脱颖而出,成功挺进10月26日的全国总决赛。与此同时,广州赛区的线上海选战果也正式揭晓:「海底大纵队」「fgs」「paperrex」「…

    2026年9月22日 • 用户投稿
    500

发表回复

登录后才能评论
关注微信