softirqs 是在 Linux 内核编译时就确定好的,例如网络收包对应的 NET_RX_SOFTIRQ 软中断。因此是一种静态机制。如果想加一种新 softirq 类型,就需要修改并重新编译内核。
我们在项目开发过程中,很多时候会出现由于某种原因经常会导致手机系统死机重启的情况(重启分Android重启跟kernel重启,而我们这里只讨论kernel重启也就是 kernel panic 的情况),死机重启基本算是影响最严重的系统问题了,有稳定复现的,也有概率出现的,解题难度也千差万别,出现问题后,通常我们会拿到类似这样的kernel log信息(下面log仅以调用BUG()为例,其它异常所致的死机log信息会有一些不同之处):
我们接着看linux初始化内存的下半部分,等内存初始化后就可以进入真正的内存管理了,初始化我总结了一下,大体分为三步:
linux 系统中,当 cpu 上没有要执行的任务时,往往会运行 swapper 进程,即 idle 状态,这时我们可以说 cpu 处于空闲状态。
基于ARMv8-A架构的处理器最大可以支持到48根地址线,也就是寻址2的48次方的虚拟地址空间,即虚拟地址空间范围为0x0000_0000_0000_0000~0x0000_FFFF_FFFF_FFFF,共256TB。
随着linux的代码更新,阅读linux-4.15代码,从中发现很多与众不同的地方。之所以与众不同,就是因为和我之前从网上博客或者书籍中看到的内容有所差异。当然了,并不是为了表明书上或者博客的观点是错误的。而是因为linux代码更新的太快,网上的博客和书籍跟不上linux的步伐而已。究竟是哪些发生了差异了?例如:kernel image映射区域从原来的linear mapping region(线性映射区域)搬移到VMALLOC区域。因此,我希望通过本篇文章揭晓这些差异。当然,我相信不久的将来这篇文章也将会成为一段历史。
KSMA的全称是Kernel Space Mirror Attack,即内核镜像攻击。本文主要记录对该攻击方法的原理分析以及Linux内核中相关内存管理部分。
2)获取对应软件版本的符号表文件(如vmlinux),可以将该文件放置 crash工具同一目录下。
内核采用“插桩”的方法抓取log,“插桩”也称为Tracepoint,Tracepoint是Linux内核预先定义的静态探测点,它分布于内核的各个子系统中,每种Tracepoint有一个name、一个enable开关、一系列桩函数、注册桩函数的函数、卸载桩函数的函数。“桩函数”功能类似于printk,不过“桩函数”并不会把信息打印到console,而是输出到内核的ring buffer(环形缓冲区),缓冲区中的信息通过debugfs对用户呈现。每个tracepoint提供一个钩子来调用probe函数。一个tracepoint可以打开或关闭。打开时,probe函数关联到tracepoint;关闭时,probe函数不关联到tracepoint。tracepoint关闭时对kernel产生的影响很小,只是增加了极少的时间开销(一个分支条件判断),极小的空间开销(一条函数调用语句和几个数据结构)。只有挂载了钩子函数才会真正启用trace功能。这个钩子函数可以由开发者编写内核module来实现,并且需要在钩子函数中获取我们调试所需要的信息并导出到用户态,这样就可以获取内核运行时的信息了。当一个tracepoint打开时,用户提供的probe函数在每次这个tracepoint执行都会被调用。
Linux系统中每个进程对应用户空间的pgd是不一样的,但是linux内核 的pgd是一样的。当创建一个新的进程时,都要为新进程创建一个新的页面目录PGD,并从内核的页面目录swapper_pg_dir中复制内核区间页面目录项至新建进程页面目录PGD的相应位置,具体过程如下:do_fork() --> copy_mm() --> mm_init() --> pgd_alloc() --> set_pgd_fast() --> get_pgd_slow() --> memcpy(&PGD + USER_PTRS_PER_PGD, swapper_pg_dir +USER_PTRS_PER_PGD, (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t))
本文一是为了讨论在Linux系统出现问题时我们能够借助哪些工具去协助分析,二是讨论出现问题时大致的可能点以及思路,三是希望能给应用层开发团队介绍一些Linux内核机制从而选择更合适的使用策略。
上一篇我们讲了 Linux 系统的启动流程,本文讲解一下 Andorid 系统的启动流程。
测试环境:Ubuntu16.04(在VMWare虚拟机使用perf top存在无法显示问题)
导言|nettrace工具自上线以来,受到了业界的广泛关注。特别是复杂的云原生网络环境中,nettrace 工具通过报文跟踪、网络诊断的方式为用户解决了多次疑难网络问题。今天就以OpenCloudOS为例,介绍在云原生场景中nettrace如何快速进行网络故障诊断。 工具简介 1)背景 在一些场景下(特别是云原生场景),Linux 系统中的网络部署变得越来越复杂。一个 TCP 连接,从客户端到服务端,中间可能要经过复杂的 NAT、GRE、IPVS 等过程,网络报文在节点(主机)上的处理路径也变得越来越长
在开源 Linux 操作系统 OpenCloudOS 8.6 中,增加了内核对网络工具 nettrace 的支持,允许开发者通过 bpf 进行网络丢包原因跟踪,内核也同时回合相关的丢包跟踪点。今天,就以 nettrace 为典型,介绍如何在 OpenCloudOS 中利用 nettrace 进行网络故障诊断。 一、工具简介 1. 背景 在一些场景下(特别是云原生场景),Linux 系统中的网络部署变得越来越复杂。一个 TCP 连接,从客户端到服务端,中间可能要经过复杂的 NAT、GRE、IPVS 等过程,网
截至目前(2023-04),Android 还未对 eBPF 程序的动态加载做出较好的支持,无论是以 bcc 为代表的带编译器分发方案,还是基于 btf 和 libbpf 的 CO-RE 方案,都在较大程度上离不开 Linux 环境的支持,无法在 Android 系统上很好地运行1。
在一些场景下(特别是云原生场景),Linux 系统中的网络部署变得越来越复杂。一个 TCP 连接,从客户端到服务端,中间可能要经过复杂的 NAT、GRE、IPVS 等过程,网络报文在节点(主机)上的处理路径也变得越来越长。在发生网络故障(比如网络丢包)时,如何快速、有效地定位出网络问题成为了一个难题。目前常规的网络故障定位手段,如 tcpdump、dropwatch、ftrace、kprobe 等存在一定的短板:
之前使用ftrace的时候需要一系列的配置,使用起来有点繁琐,这里推荐一个ftrace的一个前端工具,它就是trace-cmd
截至目前(2023-04),Android 还未对 eBPF 程序的动态加载做出较好的支持,无论是以 bcc 为代表的带编译器分发方案,还是基于 btf 和 libbpf 的 CO-RE 方案,都在较大程度上离不开 Linux 环境的支持,无法在 Android 系统上很好地运行^WeiShu。
在head_32.S中,定义了如下的BSS段,BSS段是在内核映像文件中不占空间,但是在内核被加载到内存时,会保留相应的空间。
我们对copy_{to,from}_user()接口的使用应该是再熟悉不过吧。基本Linux书籍都会介绍它的作用。毕竟它是kernel space和user space沟通的桥梁。所有的数据交互都应该使用类似这种接口。所以,我们没有理由不知道接口的作用。但是,我也曾经有过以下疑问。
作为一名程序员,肯定不仅仅限于使用API文档,因为浮于表面是远远不够的。进阶学习的阶段,需要我们保持一颗好奇的心,深入阅读Android源码,学习优秀的代码风格和设计思想,知其然并且知其所以然。
不必太纠结于当下,也不必太忧虑未来,当你经历过一些事情的时候,眼前的风景已经和从前不一样了。——村上春树
android native 代码内存泄露 定位方案(一) 什么是 AddressSanitizer clang 是一个 C、C++、Objective-C 编程语言的编译器前端。它采用 了底层虚拟机作为其后端。它的目标是提供一个 GNU 编译器套装 (GCC)的替代品, 作者是克里斯·拉特纳,在苹果公司的赞助下进 行开发。 AddressSanitizer 是 clang 中的一个内存错误检测器,它可以检测到 以下问题: Out-of-bounds accesses to heap, stack an
就在不久前我也遇到了类似的问题,看似是玄学事件,刚开始归结于网络链路抖动,一段时间后依然存在,虽然影响都是 P99.99 以后的数据,但是扰人心智,最后通过多方面定位,解决了该问题。最后发现跟业务、网络都没有什么关系,而是基础设施自身出了问题,如下文给了一个具体排查方案,并从一定程度上解释了容器、cgroup、CPU 会给网络延迟带来怎样的影响。
在初始化内存的结点和内存区域之前, 内核先通过pagging_init初始化了内核的分页机制.
虽然讲解完了内核线程的创建过程,但是似乎又少点什么,那么下面我们来看两个细节:内核线程执行处理函数和内核线程上下文切换细节:
perf除了上述的采样形式,还支持解析函数执行的完整调用栈,并得到调用栈中各个环节的cpu消耗,并对位于同一调用栈的各个环节的采样占比进行加总,得到占用cpu比例最高的顶层栈。使用如下命令进行采样
而我们的Android系统启动的过程就是架构图中从下往上运行加载的过程,这里有一张关于Android系统启动过程的总结图(图片来自参考链接gityuan.com),大家可以先看看:
/* * linux/mm/memory.c * * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds */ /* * demand-loading started 01.12.91 - seems it is high on the list of * things wanted, and it should be easy to implement. - Linus */ /* * Ok, demand-loading wa
大家好,我是程栩,一个专注于性能的大厂程序员,分享包括但不限于计算机体系结构、性能优化、云原生的知识。
通用操作系统,通常都会开启mmu来支持虚拟内存管理,而页表管理是在虚拟内存管理中尤为重要,本文主要以回答几个页表管理中关键性问题来解析Linux内核页表管理,看一看页表管理中那些鲜为人知的秘密。
primer Plus在解释具体化和实例化看的有点乱,分解出来备忘 在代码中包含函数模板本身并不会生成函数定义,它只是用于生成函数定义的方案 编译器使用模板为我写类型生成函数定义时,得到的是模板实例 如这个模板 template<typename T> void Swap(T &t1,T &t2) { T _t; _t=t1; t1=t2; t2=_t; } 调用 int i = 10,j=20; ::cout<<"i, j ="<<i<<" , "<
我们知道程序代码和数据必须驻留在内存中才能得以运行,然而系统内存数量很有限,往往不能容纳一个完整程序的所有代码和数据,更何况在多任务系统中,可能需要同时打开子处理程序,画图程序,浏览器等很多任务,想让内存驻留所有这些程序显然不太可能。因此首先能想到的就是将程序分割成小份,只让当前系统运行它所有需要的那部分留在内存,其它部分都留在硬盘。当系统处理完当前任务片段后,再从外存中调入下一个待运行的任务片段。的确,老式系统就是这样处理大任务的,而且这个工作是由程序员自行完成。但是随着程序语言越来越高级,程序员对系统体系的依赖程度降低了,很少有程序员能非常清楚的驾驭系统体系,因此放手让程序员负责将程序片段化和按需调入轻则降低效率,重则使得机器崩溃;再一个原因是随着程序越来越丰富,程序的行为几乎无法准确预测,程序员自己都很难判断下一步需要载入哪段程序。因此很难再靠预见性来静态分配固定大小的内存,然后再机械地轮换程序片进入内存执行。系统必须采取一种能按需分配而不需要程序员干预的新技术。
在linux系统中, 我们接触最多的莫过于用户空间的任务,像用户线程或用户进程,因为他们太活跃了,也太耀眼了以至于我们感受不到内核线程的存在,但是内核线程却在背后默默地付出着,如内存回收,脏页回写,处理大量的软中断等,如果没有内核线程那么linux世界是那么的可怕!本文力求与完整介绍完内核线程的整个生命周期,如内核线程的创建、调度等等,当然本文还是主要从内存管理和进程调度两个维度来解析,且不会涉及到具体的内核线程如kswapd的实现,最后我们会以一个简单的内核模块来说明如何在驱动代码中来创建使用内核线程。
通过 ps 命令可以看到红色方框标出的都是父进程为2号进程的内核线程,2号进程即蓝色方框标出的进程 kthreadd,1号进程是绿色方框标出的进程 init,它们的父进程号都是0。
之前小弟一直在宣传推广火焰图,结果是很多童鞋凡事都用火焰图。说实话,火焰图特别适合分析运行时热点(无论是on-cpu、off-cpu、还是内存等,火焰图的想象力可以无穷放大),但是你要分析一个的如果是一个时序问题,比如系统启动的慢、一个软件启动的慢,用火焰图固然可能有一点帮助,但是帮助肯定很微妙。
并发 100 个请求测试 VM1 的 Nginx 性能,总共测试 1000 个请求
在一些接口项目中,API的使用很频繁,所以一款API在线文档生成和测试工具非常有必要。而Swagger UI就是这么一款很实用的在线工具 本博客介绍如何在公司或者自己的电脑上按照Swagger UI,注意因为公司的测试服务器是Linux系统的,所以本博客也只介绍基于Linux系统的Swagger环境搭建过程
操作系统用于处理内存访问异常的入口操作系统的核心任务是对系统资源的管理,而重中之重的是对CPU和内存的管理。为了使进程摆脱系统内存的制约,用户进程运行在虚拟内存之上,每个用户进程都拥有完整的虚拟地址空间,互不干涉。而实现虚拟内存的关键就在于建立虚拟地址(Virtual Address,VA)与物理地址(Physical Address,PA)之间的关系,因为无论如何数据终究要存储到物理内存中才能被记录下来。
在工作中经常会遇到一些内核crash的情况,本文就是根据内核出现crash后的打印信息,对其进行了分析,使用的内核版本为:Linux2.6.32。
通过 Page Specific Menu Items 插件允许用户在编辑文章和页面时,选择显示的菜单项。
接上一篇BIOS启动,BIOS完成了基础的硬件检测和硬件的中断向量表的初始化,然后BIOS找到MBR并且把MBR加载在内存中,跳转到该位置。加载的位置在内存中的0x7C00,至于为什么是这个位置,主要是因为历史的原因吧,最初的内存只有32K,历史选择了0x7C00(31k)。
在32bit中的Linux内核中一般采用3层映射模型,第1层是页面目录(PGD),第2层是页面中间目录(PMD),第3层才是页面映射表(PTE)。但在ARM32系统中只用到两层映射,因此在实际代码中就要3层映射模型中合并一层。在ARM32架构中,可以按段(section)来映射,这时采用单层映射模式。使用页面映射需要两层映射结构,页面的选择可以是64KB的大页面或4KB的小页面,如图2.4所示。Linux内核通常使用4KB大小的小页面。
于浩进,linux内核爱好者,现就职于北京灵汐科技有限公司,任职BSP工程师,主要负责IP验证、多媒体驱动开发及一些bring up等工作。
FAQ_全志平台Tina3.0.7 RXXX cowbell方案启动时cpufreq报错且无法生成cpufreq节点
过去,CPU的地址总线只有32位, 32的地址总线无论是从逻辑上还是从物理上都只能描述4G的地址空间(232=4Gbit),在物理上理论上最多拥有4G内存(除了IO地址空间,实际内存容量小于4G),逻辑空间也只能描述4G的线性地址空间。
在linux内核中,所有的物理内存都用struct page结构来描述,这些对象以数组形式存放,而这个数组的地址就是mem_map。内核以节点node为单位,每个node下的物理内存统一管理,也就是说在表示内存node的描述类型struct pglist_data中,有node_mem_map这个成员,其针对平坦型内存进行描述(CONFIG_FLAT_NODE_MEM_MAP),与此相反的是SPARSEMEM,其稀疏性内存描述。
领取专属 10元无门槛券
手把手带您无忧上云