本文主要分享一个Cache一致性踩内存问题的定位过程,涉及到的知识点包括:backtrace、内存分析、efencewrap系统函数、硬件watchpointDMACache一致性等。

1 背景

设备上跑的是嵌入式实时操作系统(RTOS,具体为商业闭源的ThreadX),非Linux平台,导致一些常见的问题排查方法无法使用。

问题描述: 重启压力测试时,发现设备启动过程中偶尔会死机,概率较低。稍微修改程序后,问题可能就不再出现了,所以版本回退、代码屏蔽等方法不太适用。

2 基于backtrace分析

由于平台局限性,不支持gdb等常用调试方法,为了便于定位死机问题,本平台引入了backtrace机制,在死机的时候,会自动回溯出函数调用栈。

2.1 原理

本平台的backtrace并不是基于libc的(平台不支持),而是采用很原始的方法,当程序异常时,捕获PC寄存器和SP寄存器的值,依次回溯栈帧,从栈帧中搜索历史PC指针,进而还原出函数调用栈。

具体可以参阅:arm平台根据栈帧进行backtrace的方法

2.2 分析

死机时的堆栈如下:

Oops: CPU Exception!
pc : [<0xa000a8ac>]lr : [<0xa000a884>]
sp : 0xa37a60d8  ip : 0xa37a60d8  fp : 0x0000000b
r10: 0xa37a62c4  r9 : 0xa0fe9ab0  r8 : 0x00000000
r7 : 0x00000000  r6 : 0xa37a61c0  r5 : 0x00000000
r4 : 0x0000006c  r3 : 0x00000075  r2 : 0xa0fe9630
r1 : 0x600001d3  r0 : 0x60000113==level:0 pc:a000a8ac sp:a37a60d8==
find push in[0xa000a834], register_num=8, stack_frame_size=32
this frame size is 32
==level:1 pc:a046e900 sp:a37a60f4==
find push in[0xa046e8f0], register_num=2, stack_frame_size=8
this frame size is 8
==level:2 pc:a046b184 sp:a37a60fc==
find sub in[0xa046b0a8], stack_frame_size=228
find push in[0xa046b0a4], register_num=9, stack_frame_size=264
this frame size is 264
==level:3 pc:a040d3f4 sp:a37a6204==
find sub in[0xa040d28c], stack_frame_size=108
find push in[0xa040d288], register_num=7, stack_frame_size=136
this frame size is 136
==level:4 pc:a03e676c sp:a37a628c==
find sub in[0xa03e65dc], stack_frame_size=340
find push in[0xa03e65d4], register_num=9, stack_frame_size=376
this frame size is 376
==level:5 pc:a040b3ac sp:a37a6404==
backtrace end

PC指针0xa000a8ac对应的反汇编代码如下,可以看出,是死在了_txe_semaphore_create函数中(从上面的打印信息可以看出r5寄存器的值是0x00000000, 从下面的反汇编代码可以看出死机时在尝试访问该值偏移20字节的内存地址)。通过上面的各级PC指针进行回溯,发现回溯出来的函数都是有效的(栈被破坏的情况下,回溯出来的调用栈可能是无效的,后面会提到)。
在这里插入图片描述
虽然ThreadX不是开源的,但我们有幸在github上找到了一份开源代码,而且这份代码和我们的反汇编基本上能对应起来。_txe_semaphore_create的源码(经过裁剪,仅为示例,实际代码以参考文档1为准)如下:
在这里插入图片描述
而结构体TX_SEMAPHORE定义如下:
在这里插入图片描述
tx_semaphore_created_next在结构体TX_SEMAPHORE中正好位于起点偏移20字节的地方,结合反汇编,可以推断异常发生在函数_txe_semaphore_create中下面的语句:

next_semaphore =  next_semaphore -> tx_semaphore_created_next; 

其中右边的next_semaphore(即寄存器r5)为NULL

从这里可以看出,有信号量被破坏了。显然,这里只是问题的表象,根因并不在这里。
出问题的时候,系统中共有一百多个信号量,另外,程序运行过程中会动态的创建/销毁信号量,目前无法确定是哪里的信号量出了问题。

接下来,我们需要确认这个信号量是谁创建的?

3 确定受害者身份

3.1 ThreadX的信号量管理机制

从源码可以看出,ThreadX的信号量是以双向链表的形式维护的,如下图所示(SCBSemaphore Control Block的简称,其实就是上面的结构体TX_SEMAPHORE)。_tx_semaphore_created_ptr指向表头,另外有个全局变量_tx_semaphore_created_count说明当前总共有多少个信号量。
在这里插入图片描述
正常的信号量在内存中如下图所示,红框中为一个完整的信号量。信号量结构体中第二个字段是信号量名称,可惜我们使用的接口是被二次封装过的,无法设置信号量的名字,否则可以根据名字知道哪个信号量出问题了。
在这里插入图片描述

3.2 分析

我们可以在死机的时候,遍历信号量链表,检查现存的信号量,看看哪个出问题了。同时可以把每个信号量及其周边的内存dump出来,或许可以从这里面找到一些信息。

根据上面的思路复现后,发现某个信号量(红框内,首地址位于内存地址0xa394554c)变成了下面这个样子,面目全非了,最前面的magic等都被破坏了。从这里识别不出来这个信号量是哪里创建的。
在这里插入图片描述
不过,我们的程序托管(非hook,只是基于系统接口重新封装了一套接口)了内存申请/释放的接口,死机的时候会把当前已申请但还未释放的内存打印出来。打印信息如下,其中包含了函数名、行号、线程号、申请的内存大小、地址等信息:

[func1: 870:0xa1861368] malloc:0 bytes. offset:0 ptr:0xa394554c
[func2:2252:0xa1861368] malloc:4 bytes. offset:c ptr:0xa39455a0

可以看到,首地址为0xa394554c的内存块是由func1动态申请的。但是func1是个通用接口函数,好在只有四个地方调用了该接口,排查范围一下子缩小了很多。

注:上面的size0,是因为该值是从内存中直接解析出来的,从这里也可以看出该内存区域被破坏了,导致解析出来的内存块大小异常。后面介绍内存标记后就可以理解这里的值为啥会为0

排查代码未发现异常,那就继续添加调试信息。在每个调用func1的地方把创建的信号量地址打印出来,复现后和被破坏的信号量地址比较。这样修改后,可能是因为影响了代码的执行顺序,变得难复现了。好在还是复现出来了,最终确定了被踩信号量的身份。

后来经过多次复现,发现被踩的总是这个信号量,但是被踩后该区域的内容都是无规律的,也就是说从内存痕迹看不出是谁踩了这里。

4 谁踩了这个信号量

我们目前分析到的信息如下:

  • 被踩区域是动态申请的,内存地址是不固定的,但总是那个可怜的信号量所在的地方。
  • 代码走查发现,该信号量创建后只在特定情况下才会使用,从启动到设备出问题应该是没人用过的。

前面提到我们托管了内存申请/释放的接口,所以可以知道受害信号量前后的内存是哪里分配的。排查相关代码,均无内存越界的可能性。也就是说,临近的内存不会越界伤害到这个信号量。难道是飞来横祸,某个野指针恰好落在了这个区域?

这时候,首先想到的就是内存保护。如果能像linux那样调用mprotect函数,把这块内存设为只读属性,谁往这里写东西就会触发异常,通过调用栈可以抓到凶手。

可惜我们的平台没有mprotect这类函数。后来从驱动组同事那里了解到,可以直接通过该平台提供的MMU操作接口设置内存的只读属性。写了个demo,确实可以正常工作。

但是我们忽略了一个问题:上面提到信号量是以双向链表的形式维护的,信号量的动态创建/销毁都会操作链表,也就是会对信号量所在内存区域进行写操作,所以我们没法对信号量本身进行保护。

那么,我们是否可以借鉴LinuxElectric Fence的原理进行内存越界检测呢?

4.1 利用Electric Fence原理进行定位

Electric Fence(简称efence)是Linux平台定位堆内存非法访问问题的利器,它的优势在于事前报警而非事后,直指第一现场。efence就是基于MMU的内存访问属性来实现的,可以检测上边界溢出、下边界溢出、访问已释放内存(野指针)等问题,具体可以参考https://linux.die.net/man/3/efence。

我们打算借鉴其上下边界检测的原理。如下图所示,黄色的Data Buffer部分是用户申请的内存,灰色斜线部分是由于MMU必须按页申请而额外申请的内存,Guard page部分是被设置为不可访问属性的内存页,起保护作用。

下图左侧是向下溢出的检测原理:返回给用户的起始地址是按内存页大小对齐的,然后在用户内存的下边界处放置一个不可访问的内存页,这样当程序访问黄色区域下面的内存时,系统会立马产生异常,就可以抓到谁是凶手。

下图右侧是向上溢出的检测原理:和向下检测不同,这次是把Guard page放在用户内存的上边界处,用户内存的上边界地址必须是按内存页对齐的,下边界就不要求了。

注意:如果代码非法访问灰色区域,efence是检测不到的。
在这里插入图片描述
根据上面的原理在本平台上实现了简单的efence代码,遗憾的是,无论是上边界检测还是下边界检测,问题都不再出现。这可能和下面两个因素有关:

  • 内存布局被改变导致问题不再复现,因为正常情况下一个信号量才28个字节,但是为了使用MMU的内存保护功能,必须保证信号量的起始地址是4KB对齐的,并且被保护内存区域大小也是4KB的倍数。
  • 修改代码导致程序执行顺序发生变化,该出现的问题不再出现了。

至此,一头雾水,我们还是不知道案发现场在哪里。

4.2 加大内存检测频率

前面提到我们托管了内存申请/释放的接口,其实我们不光记录谁申请了多少内存,还在用户内存的前后加了相关标记。通过该标记,可以知道这块内存的前后边界有没有被破坏(踩内存的两种情况:上溢出和下溢出)。另外有个后台线程,定时检测已分配出去的内存有没有被破坏。

内存示意图如下所示(问题排查期间对部分字段做了冗余),图中的数字代表该字段的长度,单位是bit。最前面有个unused区域,这是因为,如果返回给用户的地址按一定字节对齐,前半部分就可能会浪费一小块内存。owner字段填充的是申请本块内存的线程号,通过该字段可以知道这块内存属于谁。
在这里插入图片描述
注:该机制还可以用来统计内存的使用情况,检测有无内存泄露。

  • 后台检测线程每秒执行一次检测任务,检测到内存被破坏后打印相关信息。该机制并未检测到这个错误,可能是由于下面两个原因:
    检测周期较长,死机的时候还没检测到,设备就挂了
  • 检测到了,但是打印还没来得及输出(输出是异步的,有缓冲),设备就挂了

抱着试试看的态度,把检测周期改为50ms,并且检测到内存错误后,立即抛出异常,防止其他程序破坏现场。

修改程序后复现,跑出来的结果也是五花八门,而且有些日志还误导了我们,以为找到了凶手,但是排查相关代码,发现那块代码并没问题。

希望再次变成失望。迷茫中,只能对一次次的死机日志进行分析,期望能找到蛛丝马迹。

其中一次死机日志引起了我们的注意,如下图所示,红色方框中是受害信号量,已经面目全非了。奇怪的是,这块内存区域已经被其他线程占用(整个黄色背景区域,已经被线程0xa3921494占用),从内存标记看,这块内存是合法申请的。
在这里插入图片描述
上图对应的内存申请记录如下:

[func1:870:0xa1864a28] malloc:2688197448 bytes. offset:501d513e ptr:0xa394552c
[func2:698:0xa3921494] malloc:116 bytes. offset:c ptr:0xa39454e8

可以看出:

0xa39454e8(func2所申请内存首地址) + 116(十进制) + 12字节的尾部标记 = 0xa3945568 >  0xa394552c(func1所申请内存首地址)

也就是说,两块内存重叠了(func1所申请内存的大小由于被破坏已经没意义了)。严格来说,func2申请的内存块,完全包含了func1的内存块。而func1是先申请的,并且从记录看并没有释放,为啥func2又申请到了这块内存?

难道谁释放了这个信号量所占用的内存?

5 谁释放了这块内存

我们设备上的内存接口示意图如下,共有两套接口,其中业务模块的接口做了内存申请释放的统计,可以确认受害信号量所在内存块没有被释放过,但是不排除已通过ThreadX自带的接口被误释放。
在这里插入图片描述

5.1 hook ThreadX自带的内存接口

为了确认这块内存有没有被释放,我们打算hook ThreadX的内存管理函数。

链接工具ld提供了–wrap选项,可以在程序链接期间进行符号替换(可参考https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_3.html)。

使用方法:在链接选项(通常为LDFALGS)中增加–wrap symbol,其中symbol为待替换的函数名、全局变量名等。

如果使用了这个选项,程序链接期间引用符号symbol的地方都将被替换为__wrap_symbol(也就是说本来调用函数symbol的地方,将调用函数__wrap_symbol),引用符号__real_symbol的地方都将被替换为symbol(也就是说本来调用函数__real_symbol的地方,将调用函数symbol)。

下面的例子hookmalloc函数,并插入了部分代码。原来程序中调用malloc的地方,都将调用__wrap_malloc,而__wrap_malloc中又调用了__real_malloc,链接期间__real_malloc会被替换为真正的、系统提供的malloc

void *__wrap_malloc (int size)
{void *ptr;/* do something you like before call malloc */ptr = __real_malloc (size);/* do something you like after call malloc */return ptr;
}

按照这个思路,我们hookThreadX的内存释放接口_txe_byte_release,发现并没有人释放这块内存。

这就奇怪了,难道ThreadX的内存管理出了问题?

5.2 ThreadX的内存管理机制

ThreadX的内存池分为Byte PoolBlock Pool两种,前者可分配任意大小的内存块,后者只能分配固定大小的内存块。我们出问题的内存属于Byte Pool,所以这里只讲述Byte Pool相关机制。

Byte Pool是用单向链表管理内存块的,下图是其初始状态。需要注意的是,该链表并不是维护在专有的内存区域,而是直接在本Byte Pool中,如果发生踩内存的情况,Byte Pool的链表有可能被破坏。
在这里插入图片描述
Byte Pool的内存分配方式是first-fit manner(最先匹配原则,与之相对的是best-fit manner),即找到第一个大于用户申请大小的内存块,并根据一定的规则对该内存块进行切割(如果该内存块大小和用户申请内存相差不大,可能就不切割了,直接给用户使用),一分为二,前者给用户使用,后者作为空闲块,留着下次使用。内存申请过程中也可能对多个连续的空闲内存块进行合并操作。

Byte Pool首次分配后的状态如下图所示,注意,如果本内存块已被分配,owner ptr区域填写的是本Byte Pool的地址,如果本内存块未被分配,填充的是0xFFFFEEEE
在这里插入图片描述

5.3 基于内存管理机制进行分析

根据ThreadX的内存管理机制,再次对4.2节提到的重叠内存区域进行分析。可以看到,下图中的[0xa39454d4, 0xa394556c)(两个next ptr之间的内存块)为一个合法的内存块,其owner ptr是正确的,next ptr也确实指向了下一个合法的内存块。而我们可怜的信号量就位于该内存块中,这块内存本属于这个信号量,在无人释放的情况下,又分配给了其他人。
在这里插入图片描述
出现该现象,可能是两种原因导致的:
ThreadX的内存管理模块出了问题
内存踩到了特定区域,把ThreadX已分配的内存块标记为Free状态了

既然暂时找不到谁破坏了这块内存,那就先确认下这块内存被破坏的时间,进一步靠近案发现场。
我们加强了内存检测机制,在每次申请/释放内存的时候都对受害信号量进行检查,如果发现异常,立即dump附近内存,并终止程序运行。示例代码如下:

void *__wrap_malloc (int c)
{void *ptr;/* 检测受害信号量内存是否被破坏 */ptr = __real_malloc (c);/* 检测受害信号量内存是否被破坏 */return ptr;
}

跑出来的结果让人瞠目结舌,从下图可以看出,红色方框里面的信号量完好无损,但是,这块区域已经被标记为free状态了。接下来如果谁申请内存,这块区域可能就给别人了。
在这里插入图片描述
不过本次实验中有个奇怪的现象,检测到信号量异常的位置,总是在malloc或者free的前面。如果是ThreadX的内存管理模块出了问题,检测到信号量异常的位置,应该在malloc或者free的后面。

基于此,可以初步排除ThreadX内存管理模块的嫌疑。但是,如果是踩内存的话,偏偏只踩了中间的0xffffeeee这四个字节,而且前面的内容没踩,后面的内容也没踩,更诡异的是,被踩区域写入的恰好是ThreadX的内存free标记。

难道ThreadX的内存管理模块不是线程安全的? 从github上的源码和实际工程的反汇编看,应该是线程安全的。为了排除该嫌疑,我们特意在hook后的malloc/free中加了把锁,结果问题还是可以出现。该嫌疑被排除。

如果把ThreadX的内存free标记改为其他的呢?踩内存的现象还会出现吗?出现的话,被写入的还是0xffffeeee吗?

基于该想法,我们把githubByte Pool的代码移植到设备上(实际工程中Byte Pool的代码我们拿不到,无法调试,和供应商确认过,github上的代码和他们提供给我们的差别不太大),并且做了以下两点改动:

  • 将内存free的标记改为0xaaaabbbb
  • 在每个标记内存块为free状态的地方加了判断,如果被free的内存块是那个信号量的,直接抛出异常。

很幸运,该代码完全可以运行,而且问题还能复现。根据复现现象,我们得到以下信息:

  • 被踩区域仍然是那个信号量
  • 进一步确认了上面的推断:不是内存管理模块将那个信号量释放的
  • 不可思议的是,被踩区域被写入的不再是0xffffeeee, 而是0xaaaabbbb

现在可以确认是踩内存问题了。 但是谁踩的呢? 这踩的也太有技术了,在相对固定的位置,写下具有特殊含义的数值,该数值还和ThreadX内存free的标记保持同步。

我真是太佩服写这个bug的人了,大写的NB!!!

6. 谁踩了这块内存

转了一圈,又回到了原点。现在梳理下目前的排查情况:

  • ThreadX内存管理模块的嫌疑已排除。
  • 内存踩的很有技巧,相对位置固定的地址,前面的内容不破坏后面的内容不破坏,偏偏只破坏了中间的四个字节,而且这四个字节和内存管理模块free状态的magic code保持一致。

这时,基本无思路了,问题就在那里,但就是抓不到凶手。不甘心,又瞎折腾了几种定位方法,虽然知道基本上无效,但是希望能影响执行时序,跑出不一样的日志,找到新线索:

  • hookmemcpymemmovestrcpy等内存操作函数,在内部检查有没有破坏那个信号量,结果没啥新发现。
  • 从反汇编中看哪些地方会写0xffffeeee到内存区域,其实从上面的实验就可以知道该方法无效了,因为即使改为0xaaaabbbb问题仍然出现。
  • 开启栈保护功能,原理和操作方法可以参考《如何在实时操作系统(RTOS)中使用GCC的栈溢出保护(SSP)功能》。同样,从上面的分析结果看,该问题不像是栈溢出导致的。实际证明加上该机制仍然没啥新发现。

6.1 硬件watchpoint

现在最有效的定位手段就是,对那四个字节做写保护,但是前面提到的MMU做不到,因为MMU的最小保护单元是一个内存页,一般为4KB

关键时刻,驱动组同事有了新想法,Linux下可以通过gdbwatchpoint监控特定内存区域,我们的系统是否也可以引入类似的机制?

通过gdb相关代码可以看到,它是利用了arm的协处理器cp14来实现的,该机制是芯片自带的,和操作系统、调试工具无关,我们的平台也可以支持。具体原理和操作方法可以参考《如何利用硬件watchpoint定位踩内存问题》。

Demo实测证明该工具超级好用,完全可以满足我们的需求。感觉终于要到开奖的时刻了,只等问题复现。
然而,现实再次给了我们一巴掌。问题复现出来了,但是该机制没检测到。真让人抓狂!!!

6.2 浮出水面的DMA

有个特殊内存块(256KB),在整个问题定位过程中,一直被我们怀疑来怀疑去,但总是找不到具体的证据。该内存和受害信号量所在内存紧挨着,并且位于受害信号量前面。几波人反复走读过相关代码找不到可疑点。但是,每次问题出现的时候,它总是和受害者相邻。

[某线程的内存  ]Index:385 Type:1. size:262172 caller:0 mem_addr:a37a6fb8 Tick:0 Diff:262180
[受害信号量内存]Index:386 Type:1. size:76 caller:0 mem_addr:a37e6fdc Tick:0 Diff:0

驱动同事问“这个内存是干嘛的”,答“读写TF卡文件用的”。这时驱动同事恍然大悟,“怪不得watchpoint抓不住,搞不好就是它了,因为Cache操作不会触发watchpoint”。
在这里插入图片描述
读写文件是经过DMA拷贝的,而我们的系统上是有Cache的,这个过程涉及Cache和主存的同步。

6.3 杀手现身

首先我们不再从内存池中动态申请这256KB内存,而是以全局数组的形式在编译期就分配好,复现了一段时间,问题果然没出现。当然不能凭此给它定罪,因为我们的问题本身出现概率就不高,有可能是改代码导致执行时序等发生变化,问题不再出现。

接下来我们进行正面验证。我们以全局数组的形式在编译期申请了512KB内存,前256KB给嫌疑模块正常使用(后面称为A),后256KB写入固定的内容(后面称为B),然后周期性检测后半部分会不会被修改。实验表明,问题没再出现,B也没被篡改,仍然没法给它定罪。

仔细想想,上面的验证逻辑有问题。假设是DMA导致的踩内存,那应该是在Cache和主存同步过程中出现的,也就是说二者的一致性出问题了。但上面的例子中,B中的内容永远是固定的,也就是说Cache和主存中是一致的。我们需要构造Cache和主存不一致的情况。

下面的代码看起来很不可思议(全局数组mem_for_sd的后256KB,即上面提到的B,只在函数change_and_check_mem中使用),先把B赋值,然后过一会再检查有没有被修改。函数change_and_check_mem在后台线程中周期性执行。
在这里插入图片描述更不可思议的是,问题很快就复现了。如下图所示,0xa182f710是B的起始地址,可以看到,有16个字节被破坏了。整个过程描述如下:
1.上次change_and_check_mem执行完,整个B被填充为0x34
2.本次执行change_and_check_mem时,先将B的填充改成0x49
3.休眠10ms
4.对B检测,发现B的前16个字节被改为0x34,而0x34是B的历史值,红色方框里也应该被填充为0x49
在这里插入图片描述
该实验证明了:真凶在此!!!
由于整个B中被填充的都是同一个值,下面两种情况无法区分:

1.B16个字节的值被缓存,而后又被赋值到原来的位置
2.B的某个字节的值被缓存,而后又将该值填充到B的前16个字节(如果是这种情况,就不太像是DMA导致的了)

为了摸清规律,我们又进行了下面的实验。和上面实验的不同之处在于,B中的值不再是一样的,而是从一个随机值递增的,到0xFF则回归到0x0
在这里插入图片描述
问题很快就又出现了,结果如下图所示,0xa182f714是全局数组B的起始地址,可以看到,有12个字节被破坏了。整个过程描述如下:

1.上次change_and_check_mem执行完,B的起始地址被填充为0x11,后面依次为0x12,0x13,每个字节加1,遇到0xff变为0x00

2.本次执行change_and_check_mem时,修改B的填充,起始地址填充为0x26,后面依次为0x27,0x28, 每个字节加1,遇到0xff变为0x00(这部分在下面的截图中看不出来,因为已经被踩了)

3.休眠10ms

4.对B检测,发现B的前12个字节被改为11121314 15161718 191a1b1c(下图红色方框内的数据),而这些值是B的历史值。红色方框内的数值应该为26272829 2a2b2c2d 2e2f3031
在这里插入图片描述
从这次实验结果看,应该是B前面几个字节的值被缓存,而后又被赋值到原来的位置。不过值得注意的是,B这次被踩了12个字节,而不是16个字节。结合B的首地址和被踩字节数,可以发现最终得到的都是0x‭a182f720(该值为32的倍数)。也就是说被踩字节数和首地址是有关联的。

第一次试验: 0xa182f710 + 16(十进制) = 0x‭a182f720
第二次试验: 0xa182f714 + 12(十进制) = 0x‭a182f720 ‬

6.4 DMACache一致性

DMA会导致Cache一致性问题。如下图所示,CPU的运算操作会修改Cache中的数据,而DMA会修改主存DDR中的数据,这就要求二者需要通过一定的机制保持同步,即Cache一致性。
在这里插入图片描述
下面的流程图展示了在内存读写过程中,Cache是如何与主存同步的,注意下面三点:

dirtyCache在被置换出去的时候,必须回写到主存(下图中的lower memory)
Cache未命中的时候,是从主存中读取原始数据的
CPU修改Cache中的数据后,并未直接回写到主存,而是将该Cache标记为dirty
在这里插入图片描述
了解了上面的原理,我们结合DMA分析下磁盘文件的读写流程。

写数据到磁盘:

  1. 判断Cache中的数据是否为dirty,如果dirty就回写到主存DDR
  2. 启动DMA将数据从主存搬运到磁盘

从磁盘读数据:

  1. 启动DMA将数据从磁盘搬运到主存DDR
  2. 将对应主存区域的Cache全部置为无效(invalid cache,注意不是dirty,这样程序访问的时候,才会从主存读取最新数据)

6.5 幕后主使在此

驱动同事分析DMA相关代码,发现本平台的Cache Line32字节,DMA操作的时候,未考虑Cache Line的对齐问题,导致Cache与主存的一致性出了问题,进而在文件读取的时候破坏了相邻的内存(大家可以思考下,为什么写文件的时候没有出问题)。以6.3节第二次实验为例,具体原因如下:
程序从文件中读取256KB的数据到下图中的内存区域A,和A紧挨着的内存区域B为另一个线程的,B的前12字节在主存中的内容和Cache中的内容不一致(结合上面介绍的知识,我们知道这是正常的)。
在这里插入图片描述
DMA将文件读取到主存的A区域后,需要将A区域对应的Cache invalid(失效)掉,以保证Cache和主存中的数据是一致的。
注:实际上,A对应的内存区域可能已经不在Cache中了,但DMA不知道,为了保证数据的一致性,它必须将A对应的Cache invalid掉。

Invalid Cache的时候就带来问题了。前面提到本平台的Cache Line为32字节,也就是说一次进入Cache或清除Cache的最小单位是32字节,而A的首地址为0xa182f714,大小为256KB,为了保证整个A区域的Cache被清除,必须清除至地址0x‭a182f720。计算方法为:按32字节的倍数向上对齐,如下所示:
ROUND_UP(0xa182f714 + 0x40000, 32) = 0x‭a182f720

B现在最新的数值是在Cache中,而上面的操作会将B前12字节对应的Cache invalid掉。如下图所示,后续程序再访问B的前12字节,cache未命中,只有从主存中取,结果取到的是历史值。
在这里插入图片描述
就这样,B躺着中枪了!!!

实际程序中,那个可怜的信号量就在上面的B处。

7. 修改方法

由于本平台的Cache Line32字节,所以我们需要保证拿去做DMA的内存首地址32字节对齐,并且大小也是32字节的倍数。这样就不会出现上面的踩内存问题。

7.1 方法一:应用层规避

所有使用DMA的业务代码,自行保证内存首地址和大小均按32字节对齐。但是该方案存在以下明显的缺点:

  • 上层业务必须知道哪些接口是使用DMA
  • 有些内存变量的对齐不好做,比如栈上的局部变量
  • 增加了上层业务开发的复杂度

7.2 方法二:驱动层规避

比较合理的解决方法是,驱动层保证。如下图所示,驱动层识别到首地址不是32字节对齐的,就先用一个临时内存块(该临时内存块首地址32字节对齐,大小是32字节倍数)做前12字节的DMA,然后将前12个字节通过memcpy拷贝到主存的0xa17ef714~0xa17ef720,接下来的1024字节因为满足对齐和大小要求,所以可以直接进行DMA,尾部剩余14字节只满足首地址对齐的要求,不满足大小是12字节倍数的要求,所以也要借助临时内存完成数据搬运。
在这里插入图片描述

8 总结

本文涉及的知识点如下:

1.backtrace回溯函数调用栈
2.汇编代码分析
3.内存打标记,及基于此的内存非法访问检测
4.基于MMU的内存保护
5.Electric Fence(efence)内存非法方法检测机制
6.通过wrap链接选项替换系统函数
7.基于GCC的栈溢出保护(SSP)功能
8.硬件watchpoint
9.TheadX内存管理机制、信号量管理机制
10.DMA、Cache一致性

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

相关文章

  1. linux基础服务(DHCP)

    DHCP篇 文章目录DHCP篇DHCP是什么DHCP工作原理DHCP三种分配机制搭建DHCP DHCP是什么 DHCP,动态主机配置协议(Dynamic host configuration protocol),是一个局域网络协议,使用的是UDP协议工作,是给内部局域网或者网络供应商自动分配IP地址,是给用户或者内部网络的网管来作为…...

    2024/5/1 8:09:13
  2. 你了解Kotlin的let,with,run,apply,also关键函数的区别吗?

    前言: 成和败要努力尝试,人若有志应该不怕迟。一、概述Kotlin提供了不少比Java高级的语法,在Kotlin标准库中(Standard.kt)提供了一些Kotlin拓展的内置函数,可以优化编码。Standard.kt是Kotlin库的一部分,它定义了一些基本函数,功能非常强大。 1.1 Kotlin回调函数的优化 K…...

    2024/4/28 16:15:47
  3. 外贸企业邮箱如何选择?

    作为一名外贸人,深知外贸企业邮箱的重要性!外贸小伙伴们与国外客户沟通,除了wechat、skype和whatsapp基本都是靠企业邮箱去沟通。那么该如何挑选适合自己的外贸企业邮箱呢? 1、企业邮箱的后缀,最好为行业产品关键词,这样对方一看就知道咱们是做什么行业。 2、邮箱域名选好…...

    2024/4/24 12:06:04
  4. 安卓wifi基础功能

    一 相关概念介绍 1 涉及到的类WifiManager ——与Wifi相关的所有操作均通过此类 WifiConfiguration——Wifi网络配置信息 WifiInfo——表示当前的wifi热点信息 ScanResult——扫描到的热点信息类AccessPoint:这里先自行定义一个对象,方便描述和讲解,结构如下: public cla…...

    2024/4/24 12:06:01
  5. NRA离岸账户的注册条件和流程

    目前国内NRA离岸开户最方便的银行无疑是稠州商业银行了,该银行虽然是浙江省地方银行,其名气不大知名度不高,但该银行为浙江省扶持银行,稳定,安全。大家若是想该银行开户无需但心资金进出是否安全,该银行开设了很多的离岸账户,客户的操作和回馈对该银行都是很不错的体验。…...

    2024/4/24 12:06:06
  6. 如何免费安装并激活序列号iMazing软件

    iMazing是一款能够快速传输和保存音乐、文件、照片以及进行备份的iOS设备管理软件,同时支持Mac和Windows两大系统,功能强大,便于使用,下面小编就通过一则简单的教程,教大家如何下载安装并激活iMazing。 先行声明,本教程是在Windows10操作系统上,使用iMazing 2版本为大家…...

    2024/4/24 12:06:06
  7. 拿到软考证书到底会有哪些作用?

    软考证书还是非常有用的,特别是在IT行业。证书是大家求职的敲门砖。 那么拿到软考证书到底会有哪些作用呢?自我能力的提升。软考中级的系统集成项目管理工程师,高级的信息系统项目管理师,旨在考查IT在项目管理方面的实践与应用,除了IT的基础技术外,同时有项目管理的5大过…...

    2024/4/24 12:06:04
  8. 2020,8种必备Selenium编写自动化用例的技巧

    在开始自动化时,您可能会遇到各种可能包含在自动化代码中的方法,技术,框架和工具。有时,与提供更好的灵活性或解决问题的更好方法相比,这种多功能性导致代码更加复杂。在编写自动化代码时,重要的是我们能够清楚地描述自动化测试的目标以及我们如何实现它。话虽如此,编写…...

    2024/5/1 8:48:20
  9. 简书大佬的笔记:一篇文章带你详解 HTTP 协议(网络协议篇一)

    一篇文章带你详解 HTTP 协议(网络协议篇一)本篇文章篇幅比较长,先来个思维导图预览一下。一张图带你看完本篇文章一、概述1.计算机网络体系结构分层计算机网络体系结构分层2.TCP/IP 通信传输流利用 TCP/IP 协议族进行网络通信时,会通过分层顺序与对方进行通信。发送端从应用…...

    2024/4/24 12:05:57
  10. Spring 常见面试题

    1.Spring是什么? 答:Spring是一个轻量级的IoC和AOP容器框架,是为java应用程序提供基础性服务的一套框架,常见的配置方式有三种:基于XML配置,基于注解配置,基于java配置 主要由以下几个模块组成: Spring core:核心类库,提供IoC服务; Spring context:提供框架式的bea…...

    2024/4/27 14:39:23
  11. 公式顺序解析之加减乘除的执行顺序

    在上文:java根据Stack栈实现公式解析和自定义函数(二)的结尾有三个问题1. 加减乘除只支持两位2. 前缀的加减乘除还不支持3. 在末尾加减乘除会遇到数组下标越界的问题博主的思路已经有些混乱了,感觉不太对,所以我们先来把加减乘除的解析计算写一下,自己也捋捋思路,有经验…...

    2024/4/27 13:55:47
  12. allegro一键换层快捷命令设置

    allegro一键换层.txtallegro一键换层的快捷键设置,亲测好用,本人从网上找了N久才总结出来的,希望对各位攻城狮有所帮助,需要的自己下载吧立即下载allegro一键换层的快捷键设置,亲测好用,本人从网上找了N久才总结出来的,希望对各位攻城狮有所帮助,需要的自己下载吧...

    2024/4/27 14:16:36
  13. Python Pytest中使用的装饰器pytest.fixture

    最近在pytest中使用了很多装饰器觉得很好用,现在总结一下:pytest.fixture一、通过装饰器@pytest.fixture(),定义测试固件(test fixture)。实现setup_xxx的功能: import pytest # 函数名自定义 # 此时,login函数是一个测试固件,相对于实现了setup_xxx的功能。 @pytest.f…...

    2024/4/27 16:50:48
  14. PHP基本知识了解掌握 新手ctf 开源CMS 寻找EXP

    PHP概述PHP基本常识(了解)PHP基本语法(掌握)PHP网站框架指纹识别 PHP基本常识(了解)PHP定义 Personal Home Page Tools 原始定义 Hypertext Preprocessor 当前定义 超文本预处理器 是一种被广泛应用的开放源代码的多用途语言 PHP是服务器端脚本,返回的是HTML代码 与php…...

    2024/4/27 14:26:43
  15. Python虚拟环境搭建(Linux)

    1. 安装python3 sudo apt install python32. 安装pip3 sudo apt install python3-pip3. 安装virtualenv sudo -H pip3 install virtualenv3. 安装virtualenvwrapper sudo -H pip3 install virtualenvwrapper4. 配置virtualenvwrappervim ~/.bashrcexport WORKON_HOME=~/virenv…...

    2024/4/27 14:51:37
  16. JVM配置方法

    1、调优目的减少GC的频率和Full GC的次数2、调优方法使用jmap、mat等工具进行堆使用情况分析,内存等分析,通过调优参数重复分析使用情况,直到参数最优。3、工具的使用(1)jmap观察运行中的jvm物理内存的占用情况。参数如下:-heap :打印jvm heap的情况,会列出堆的总体使用情…...

    2024/4/27 15:08:46
  17. Java之jdbc

    ...

    2024/4/30 5:15:52
  18. leetcode46:

    描述:给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。来源:力扣(LeetCode) 链接:https://le…...

    2024/4/27 14:20:32
  19. 二级目录安序号文件重命名

    # coding = utf-8 import osdef rename(path):i = 0该文件夹下所有的文件(包括文件夹)FileList = os.listdir(path)遍历所有文件for files in FileList:原来的文件路径oldDirPath = os.path.join(path, files)如果是文件夹则递归调用if os.path.isdir(oldDirPath):rename(old…...

    2024/4/27 16:41:20
  20. GitBook部署与编写使用

    记录下gitbook文章目录介绍部署安装Node.js安装gitbook使用配置说明插件配置GitBook Editor编写创建文件夹或目录编写目录git push/pull 介绍 GitBook是一个基于Node.js的命令行工具,可使用Git和Markdown来编写文档。 总结几点:多人协作管理文档 文件服务 book发布 markdown编…...

    2024/4/27 15:55:00

最新文章

  1. java-springmvc 01 补充 javaweb 三大组件Servlet,Filter、Listener(源码都是tomcat8.5项目中的)

    01.JavaWeb三大组件指的是&#xff1a;Servlet、Filter、Listener,三者提供不同的功能 这三个在springmvc 运用很多 Servlet 01.Servlet接口&#xff1a; public interface Servlet {/*** 初始化方法* 实例化servlet之后&#xff0c;该方法仅调用一次 * init方法必须执行完…...

    2024/5/1 9:58:41
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. Git的简单使用

    Git 一&#xff1a;什么是Git&#xff1a; Git是一个分布式版本控制系统&#xff0c;用于跟踪文件的变化并协作开发项目。它允许多个开发者在同一时间内对同一个项目进行编辑&#xff0c;并能够轻松地管理不同版本的文件。Git通过记录文件的变化并创建快照来跟踪项目的历史记…...

    2024/4/30 9:12:05
  4. Django实现的登录注册功能

    1 前言 在Web开发中&#xff0c;用户登录和注册是最基本且必不可少的功能。Django&#xff0c;作为一个高级的Python Web框架&#xff0c;为我们提供了强大的工具和库来快速实现这些功能。下面&#xff0c;我将详细介绍如何使用Django来实现用户登录和注册功能。 2 功能介绍 …...

    2024/4/30 3:22:29
  5. vue3项目运行正常但vscode红色波浪线报错

    以下解决办法如不生效&#xff0c;可尝试 重启 vscode 一、Vetur插件检测问题 vetur 是一个 vscode 插件&#xff0c;用于为 .vue 单文件组件提供代码高亮以及语法支持。但 vue 以及 vetur 对于 ts 的支持&#xff0c;并不友好。 1、原因 如下图&#xff1a;鼠标放到红色波浪…...

    2024/4/30 10:04:45
  6. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/4/29 23:16:47
  7. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/30 18:14:14
  8. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/29 2:29:43
  9. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/30 18:21:48
  10. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  11. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  12. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  13. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/30 9:43:09
  14. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  15. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/25 18:39:16
  16. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  17. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  18. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/29 20:46:55
  19. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/30 22:21:04
  20. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/1 4:32:01
  21. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  22. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  23. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/30 9:42:22
  24. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/30 9:43:22
  25. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/30 9:42:49
  26. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  27. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  28. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  29. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  30. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  31. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  32. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  33. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  34. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  35. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  36. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  37. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  38. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  39. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  40. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  41. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  42. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  43. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  44. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  45. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57