![[Android稳定性] 第024篇 [方法篇] RCU Stall问题如何进行分析?](https://hexoimg.oss-cn-shanghai.aliyuncs.com/blog/24/12/cover_how_to_debug_rcu_stall_issue.png) 8月前
        
        
            
                评论
        
        
        8月前
        
        
            
                评论
            
            
        
        
        
    [Android稳定性] 第024篇 [方法篇] RCU Stall问题如何进行分析?
RCU(读-复制-更新)是一种针对多核、多线程环境的内存同步机制,旨在解决读写并发问题,特别适用于读多写少的场景。RCU Stall是指RCU子系统检测到的问题,如宽限期未结束、回调堆积或调度延迟等,可能导致系统性能下降。分析RCU Stall的方法包括检查内核日志、任务栈回溯、长时间运行的任务、锁和资源争用等。实例中,通过dmesg日志分析和打开panic_on_rcu_stall来复现问题,并通过串口输出进程信息进行深入诊断。
![[linux内存管理] 第21篇 buddy内存管理之快速分配](https://halo-19274848.oss-cn-shanghai.aliyuncs.com/2025/06/halo_zarkuub.png?x-oss-process=image/resize,w_800,m_lfit) 8月前
        
        
            
                评论
        
        
        8月前
        
        
            
                评论
            
            
        
        
        
    [linux内存管理] 第21篇 buddy内存管理之快速分配
### 4. 慢速分配 当快速分配无法满足分配请求时,会进入慢速分配流程。 ```c static struct page *__alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, struct alloc_context *ac) { gfp_t alloc_flags = ALLOC_WMARK_LOW | ALLOC_CPUSET; unsigned int alloc_flags_idx = ALLOC_INDEX(gfp_mask); struct zone *zone; nodemask_t *alloc_nodemask; int alloc_nid; struct pglist_data *pgdat; struct page *page = NULL; unsigned long mark; /* The fallback path may need to allocate memory on another node */ alloc_nid = numa_node_id(); /* * On the first allocation attempt, we try to allocate from the * preferred zone only. On the second attempt, we try to allocate * from the whole zonelist. */ if (ac->preferred_zoneref->zone != NULL) zone = ac->preferred_zoneref->zone; else zone = NULL; /* * The first allocation attempt can ignore memory policy. For the * second attempt, we need to honor the memory policy. */ if (ac->nodemask == &cpuset_current_mems_allowed) { alloc_nodemask = NULL; alloc_flags &= ~ALLOC_CPUSET; } else { alloc_nodemask = ac->nodemask; } pgdat = zone->zone_pgdat; alloc_flags |= pgdat->alloc_flags; /* If we are re-filling the per-cpu pageset, then honor the * zone reclaim mode. */ if (order == 0 && ac->pcp) { alloc_flags |= pgdat->alloc_flags; if (!node_reclaim_enabled()) alloc_flags &= ~ALLOC_CPUSET; } /* * We have already checked if the zone is online and the node is * online. If the zone is not online, we cannot use it for * allocation. If the node is not online, then it is possible * that the zone is online but the node is not. If we cannot use * the zone, then we must use a different node. */ if (!zone->node->online) { zone = NULL; alloc_nid = numa_next_node(alloc_nid, alloc_nodemask); if (alloc_nid == NUMA_NO_NODE) { if (alloc_flags_idx == ALLOC_INDEX(GFP_KERNEL)) { return NULL; } alloc_flags_idx = ALLOC_INDEX(GFP_KERNEL); alloc_flags &= ~ALLOC_CPUSET; alloc_flags &= ~ALLOC_WMARK_LOW; alloc_flags |= ALLOC_WMARK_MIN; goto retry; } pgdat = NODE_DATA(alloc_nid); alloc_flags |= pgdat->alloc_flags; } /* We are going to sleep. If this allocation is for a page cache * page, then we want to go to sleep only if the dirty pages are * within the limit. */ if (!ac->spread_dirty_pages && !node_dirty_ok(pgdat)) { if (alloc_flags_idx == ALLOC_INDEX(GFP_KERNEL)) { return NULL; } alloc_flags_idx = ALLOC_INDEX(GFP_KERNEL); alloc_flags &= ~ALLOC_CPUSET; alloc_flags &= ~ALLOC_WMARK_LOW; alloc_flags |= ALLOC_WMARK_MIN; goto retry; } /* * The zone has enough free pages. We can allocate a new page. */ if (zone_page_state(zone, NR_FREE_PAGES) >= zone_page_state(zone, NR_ZONE_FREE_MIN) + (1 << order)) { alloc_flags &= ~ALLOC_CPUSET; } retry: alloc_flags |= gfp_to_alloc_flags(gfp_mask, alloc_flags_idx); /* If the zone is not online, we need to allocate from another zone. */ if (!zone) { if (!alloc_nodemask) { zone = zone_reclaim(zone, gfp_mask, order); if (zone) goto retry; } else { zone = zone_reclaim_nodemask(pgdat, gfp_mask, order); if (zone) goto retry; } } /* * If we are here, it means that we have found a zone that has enough * free pages and we can allocate a new page. */ if (zone_page_state(zone, NR_FREE_PAGES) >= zone_page_state(zone, NR_ZONE_FREE_MIN) + (1 << order)) { page = get_page_from_freelist(gfp_mask, order, alloc
![[linux内存管理] 第020篇 Linux内核slab内存的越界检查SLUB_DEBUG的原理剖析](https://hexoimg.oss-cn-shanghai.aliyuncs.com/blog/25/2/cover_linux_memory_management_020.png) 8月前
        
        
            
                评论
        
        
        8月前
        
        
            
                评论
            
            
        
        
        
    [linux内存管理] 第020篇 Linux内核slab内存的越界检查SLUB_DEBUG的原理剖析
copyright_author: 蜗窝科技 copyright_author_href: http://www.wowotech.net copyright_url: http://www.wowotech.net/memory_management/427.html copyright_info
![[Android稳定性] 第023篇 [问题篇] printk非空的非法指针参数导致的spinlock死锁引起Non Secure WDT](https://hexoimg.oss-cn-shanghai.aliyuncs.com/blog/25/2/cover_android_stability_023.png) 8月前
        
        
            
                评论
        
        
        8月前
        
        
            
                评论
            
            
        
        
        
    [Android稳定性] 第023篇 [问题篇] printk非空的非法指针参数导致的spinlock死锁引起Non Secure WDT
**摘要**: 本文分析了Linux内核中因`Non secure wdt`导致的死机问题。通过分析ramdump,发现所有CPU都在等待一个spin lock,且锁的持有者是`kworker/u17:12`。进一步分析发现,该进程在获取锁后出现了data abort,并在异常处理流程中再次尝试获取锁,导致死锁。根本原因是`nvt_update_firmware`函数中使用了未初始化的指针作为`printk`的参数,导致打印异常。解决方案是将`kmalloc`改为`kzalloc`,以确保内存被清零。实验验证了当`printk`的参数为非法指针时,会导致死锁。
![[Android稳定性] 第022篇 [原理篇] kernel panic的死亡信息的由来](https://hexoimg.oss-cn-shanghai.aliyuncs.com/blog/25/1/cover_android_stability_022.png) 9月前
        
        
            
                评论
        
        
        9月前
        
        
            
                评论
            
            
        
        
        
    [Android稳定性] 第022篇 [原理篇] kernel panic的死亡信息的由来
本文主要介绍了 Linux 内核稳定性问题中的“kernel panic”现象,并深入分析了其产生的原因、异常处理流程以及如何处理。文章以一个具体的异常案例为切入点,详细解释了异常信息的解读、异常向量表的查找、异常处理函数的执行过程,并最终揭示了 panic 报错信息的来源。文章还介绍了 oops_enter、console_verbose、__die、dump_backtrace 等关键函数的功能,以及 panic_on_oops 内核参数对 panic 流程的影响。通过本文的学习,读者可以更好地理解内核 panic 的产生机制,并掌握相应的调试方法。
![[Android稳定性] 第021篇 [问题篇] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted](https://halo-19274848.oss-cn-shanghai.aliyuncs.com/2025/06/halo_jhqyzy1.png?x-oss-process=style/watermark&x-oss-process=image/resize,w_800,m_lfit) 9月前
        
        
            
                评论
        
        
        9月前
        
        
            
                评论
            
            
        
        
        
    [Android稳定性] 第021篇 [问题篇] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted
### 文章摘要 本文探讨了在Android系统中出现的一个内核崩溃问题,具体表现为`Kernel panic`错误,并深入分析了崩溃的原因。通过对内核日志和进程栈的解析,发现崩溃发生在`mi_binder_wait4_hook`函数中,由于栈帧指针`x29`发生`bitflip`错误,导致从错误的地址读取值,触发`__stack_chk_fail`函数,最终导致内核崩溃。文章详细介绍了如何通过分析汇编代码和进程栈来定位问题,并提出了可能的解决方案,即添加`nop`指令来防止`bitflip`问题。
![[Android稳定性] 第020篇 [方法篇]  crash实战:手把手教你使用crash分析内核dump](https://hexoimg.oss-cn-shanghai.aliyuncs.com/blog/25/1/cover_android_stability_020_d72a61900b5d80ca3b1a9b3aeea2d6c4.png) 9月前
        
        
            
                评论
        
        
        9月前
        
        
            
                评论
            
            
        
        
        
    [Android稳定性] 第020篇 [方法篇] crash实战:手把手教你使用crash分析内核dump
本文介绍了使用crash工具分析Linux内核崩溃(Kdump)的方法,重点针对手机领域。crash工具在处理大型dump文件时比trace32更加高效,因为它不会占用大量内存资源。文章还探讨了crash工具在恢复任务调用栈、查看局部变量值等方面的实用技巧,以及如何查找访问特定变量的线程。通过crash工具,开发者可以更有效地定位和解决内核崩溃问题,提高问题定位的效率。
![[Android稳定性] 第019篇 [原理篇] QCOM 常见 reboot 类型流程梳理](https://hexoimg.oss-cn-shanghai.aliyuncs.com/blog/25/1/cover_android_stability_019.png) 9月前
        
        
            
                评论
        
        
        9月前
        
        
            
                评论
            
            
        
        
        
    [Android稳定性] 第019篇 [原理篇] QCOM 常见 reboot 类型流程梳理
本文详细梳理了Android设备的三种重启类型:ADB重启、电源键重启(包括长按电源键直接重启和弹窗重启)以及panic重启。通过分析源代码,揭示了每种重启类型的流程,包括重启动作、事件处理、服务关闭、文件系统同步、内存清理等步骤。文章还探讨了重启前系统属性的处理流程,以及重启后如何从寄存器中获取重启原因,并传递给ABL阶段。最后,文章以高通项目为例,说明了重启流程中内核通知链的作用,以及重启后如何根据重启原因启动不同的系统模式。
![[Android稳定性] 第018篇 [问题篇] 串口日志未关闭导致的watchdog](https://hexoimg.oss-cn-shanghai.aliyuncs.com/blog/25/1/cover_android_stability_018.png) 9月前
        
        
            
                评论
        
        
        9月前
        
        
            
                评论
            
            
        
        
        
    [Android稳定性] 第018篇 [问题篇] 串口日志未关闭导致的watchdog
系统出现死机,日志显示QCOM Apps Watchdog超时触发。分析发现,所有CPU核心均暂停等待`rcu_momentary_dyntick_idle`,CPU0正在执行打印操作,导致无法及时pet watchdog,引发异常。解决方案建议关闭kernel的串口日志以避免类似问题。
![[Android稳定性] 第017篇 [方法篇] 高通watchdog分析流程](https://hexoimg.oss-cn-shanghai.aliyuncs.com/blog/25/1/cover_android_stability_017.png) 9月前
        
        
            
                评论
        
        
        9月前
        
        
            
                评论
            
            
        
        
        
    [Android稳定性] 第017篇 [方法篇] 高通watchdog分析流程
高通watchdog分析七步法:首先检查执行状态,确认进程位置和状态;若未就绪,探究timer问题;若就绪未调度,分析中断及调度状况;最后检查进程是否禁止抢占,确保系统稳定运行。
 
    