- 博客(219)
- 资源 (7)
- 收藏
- 关注
原创 分析匿名页(anonymous_page)映射
接着上一次malloc(探秘malloc是如何申请内存的)的dump信息继续分析。-006|do_anonymous_page(inline) | vma = 0xFFFFFFE314E27310 | tsk = 0xFFFFFFE300786640 | entry = (pte = 0x00E800026F281F53)-006|handle_pte_fau...
2020-04-28 11:11:24 2853
原创 手动玩转虚拟地址到物理地址转化
我们这次来根据dump动手来实际转化一个虚拟地址到物理地址,此次的地址不是线性地址映射。Target_Address_|________________logical|_physical______________| | C:FFFFFF8008015000| A:C549F000 上面0xFFFFFF8008015000就...
2020-04-28 10:34:31 1893
原创 学习ARM64页表转换流程
在引入虚拟地址概念以后,程序员和CPU看到的都是虚拟地址。当CPU尝试去访问某个虚拟地址的时候,这时候硬件单元MMU就会将此虚拟地址转化为物理地址,然后CPU再去访问。而在Linux中存储虚拟地址到物理地址转化的关系的表称为页表。目前最新的linux内核已经支持了5级页表。下图是一个4级页表的转化关系图。PGD(Page Global Directory)页全局目录 PU...
2020-04-28 10:23:59 3542 1
原创 Kmalloc申请内存源码分析
再上一节了解了SLUB是如何申请一个object的,其中涉及了从当前的freelist申请,以及kmem_cache_cpu->partital链表申请,以及到最后的kmem_cache_cpu→node中申请,如果上述三个步骤都没有申请到的话,就会重新创建一个新的slab,然后设置好freelist的指针,返回object使用。本节我们重点分析下Kmalloc的实现,其实在驱动中...
2020-04-27 18:16:26 2096
原创 SLUB分配一个object的流程分析
在上一节 我们清晰的知道了当调用kmem_cache_create之后系统会为我们分配一个名为slub_test的一个slab。这时候只是分配了kmem_cache,kmem_cache_cpu,kmem_cache_node结构,同时设置针对此object需要多少个page之类。我们这节将分析当申请一个object的时候,应该是如何的分配。还是之前的例子,继续来分析当调用kmem_cache...
2020-04-27 16:18:14 1206 1
原创 SLUB结构体创建及创建slab分析
在上一篇文章中我们通过一个简单的例子大概描述了如何创建SLUB缓存,如何分配一个object。本文详细描述下涉及的结构体,从结构体的描述中就可以大概理解slub的工作原理了。首先就是kmem_cache结构体/* * Slab cache management. */struct kmem_cache { struct kmem_cache_cpu __percpu ...
2020-04-26 16:28:38 1077
原创 SLUB的引入及举例说明
我们都知道Buddy分配器是按照页的单位分配的(Buddy系统分配器实现),如果我们需要分配几十个字节,几百个字节的时候,就需要用到SLAB分配器。SLAB分配器专门是针对小内存分配而设计的,比如我们驱动中常见的Kmalloc分配器就是通过SLAB分配器分配的内存。而SLAB分配器在linux系统中三种具体的实现:SLAB,SLUB,SLOB。目前内核代码中默认的SLAB分配器为SLUB算...
2020-04-26 11:06:57 1110
原创 page compaction代码分析之一
重要的数据结构/* * Determines how hard direct compaction should try to succeed. * Lower value means higher priority, analogically to reclaim priority. */enum compact_priority { COMPACT_PRIO_SYNC_F...
2020-04-23 15:56:54 548
原创 page compaction原理
参考:https://lwn.net/Articles/368869/先看一个例子:如果你的ubuntu机器经过长时间运行,比如1个月没关机,这时候你去看buddinfo和pagetypeinfo的信息。root@root# cat /proc/buddyinfoNode 0, zone DMA 3 3 1 1 ...
2020-04-22 18:25:58 670 1
原创 zone watermark水位控制
本节我们来分析下zone的水位控制,在zone那一节中,我们将重点放在了free_area中,故意没有分析zone中的水位控制,本节在重点分析zone中的水位控制。struct zone { /* zone watermarks, access with *_wmark_pages(zone) macros */ unsigned long watermark[NR_WM...
2020-04-21 17:55:52 2771
原创 快车道-分配页
内核提供如下函数用于分配页:alloc_pages(gfp_mask, order) //用于分配一个order阶数的页alloc_page(gfp_mask) //用于分配一页,最终调用的是alloc_pages(gfp_mask, 0)那我们就分析alloc_pages的具体实现static inline struct page *...
2020-04-20 18:05:01 451
原创 从备用类型总盗用steal page
在之前的文章中,当分配一页的时候从对应order的对应的迁移类型中freelist中分配一个空闲的页。但是也会出现此order的迁移类型中没有可用的page,这时候就会从备用的迁移类型中盗用pagestatic __always_inline struct page *__rmqueue(struct zone *zone, unsigned int order, int migratet...
2020-04-18 11:42:36 1895 1
原创 Buddy分配器之释放一页
在上面一节我们讲述了buddy分配器是如何分配一页的,本节我们在学习buddy分配器是如何释放一页的分配一页的算法:比如当前释放order=n的页获得当前释放order=n的页,对应的buddy,也就是兄弟页,俗话说先找到兄弟 找到兄弟buddy了之后,接下来就是看buddy和此页是否可以合并 检查buddy是否是空闲的页(通过检查page→private是否为0) 检查b...
2020-04-16 17:01:32 1056
原创 Buddy(伙伴)系统分配器之分配page
Buddy分配器是按照页为单位分配和释放物理内存的,在Zone那一节文章中freearea就是通过buddy分配器来管理的。buddy分配器将空闲页面按照order的大小分配挂到不同的order链表中。比如order为0的链表下就挂载着大小为1个page的空闲页,order=4的链表下就挂载着大小为16个page的空闲页面。buddy分配器的算法是:当分配order=n的页面的时候...
2020-04-15 10:44:52 1841
原创 物理内存管理之zone详解
上一次说过了物理内存由node,zone,page三级结构来描述。而node是根据当前的系统是NUMA还是UMA系统。假设我们当前是UMA系统架构,则只有一个node。我们本节则重点学习下ZONE,重点是ZONE的数据结构,其中就可以看到ZONE中是如何管理我们page的,就会看到buddy分配器。struct zone { unsigned long _watermark[...
2020-04-11 13:45:14 4256
原创 物理内存是如何组织管理的
内存管理,相比大家都听过。但是内存管理到底是做什么呢?这就得从计算机刚出来的时候说起。计算机刚出来的时候内存资源很紧张,只有几十K,后来慢慢的到几百K,到周后来的512M,再到现在的几个G。真是因为内存资源的不足,在计算机的整个过程中衍生出各种各样的内存管理方法。而内存管理的终极目标就是合理的不浪费的使用物理内存。Linux针对如何合理的使用物理内存,软件上设计了多种的内存管理方法。今天我们就...
2020-04-10 11:35:40 1090 1
原创 VMA实战操练
在上篇文章根据crash学习用户空间程序内存布局涉及到了VMA的相关操作,本节通过一个简单的实例来深刻的学习下VMA是什么,以及VMA是如何组织的。先来看下VMA的结构体struct vm_area_struct { /* The first cache line has the info for VMA tree walking. */ unsigned long vm_s...
2020-04-09 16:44:26 993
原创 根据crash学习用户空间程序内存布局
在32位机器上,总共有4G大小的虚拟地址空间,其中0-3G是给应用程序使用,3-4G是给内核使用。在64位机器上,目前还不完全支持64位地址宽度,常见的地址长度有39(512GB)和48位(256TB),目前我使用的模拟器采用的是39位的地址宽度,这样的话用户空间和内核空间各占512GB的地址空间。当一个应用程序在用户跑起来的时候,它内部是如何正常运行的,通过一个简单的例子详细说明下...
2020-04-08 17:49:03 694
原创 根据crash学习ARM64虚拟地址空间布局
我们先来看一个出错的现场:[ 55.195101] Unable to handle kernel paging request at virtual address ffffdfc7be9c2100[ 55.195107] Mem abort info:[ 55.195109] ESR = 0x96000004[ 55.195112] Exception cl...
2020-04-08 11:02:49 11678 2
原创 GICv3驱动初始化
linux驱动支持GICv1, GICv2, GICv3, GICv4驱动,本节我们重点来描述下GICv3的驱动初始化,结合ARM-Cortex平台详细描述intc: interrupt-controller@666688888 { compatible = "arm,gic-v3"; #interrupt-cells = <3>; ...
2020-04-02 18:36:07 1590
原创 ARMv8-A Generic Interrupt Controller(GIC)
本节描述下ARM架构下的中断控制器,The Generic Interrupt Controller(GIC)ARM架构下GIC支持好几个版本,GIC-v1, GIC-v2, GIC-v3, GIC-v4本系列文章重点聚焦在GIC-V3版本,而GIC-V3版本的典型代表就是GIC-500关于GIC-500的特性GIC-500可以最大支持128Cores GIC-500目前只...
2020-04-01 18:05:21 3188 1
原创 ARMv8-A Exception Handling
本节来详细描述下ARMv8-A下的异常处理。异常的概述:当设备正在愉快的执行时候,此时发生了一个异常,处理器就必须暂停当前的任务,转而去处理发生的异常。当异常处理完毕后,处理就会发回到被打断的程序继续执行。此图就是描述异常的处理流程。异常的分类:异常分为同步异常和异步异常,而这两种异常的区别是:同步异常:如果异常的产生是通过执行指令,而且返回结果提供了产生异...
2020-03-31 18:26:52 1421
原创 ARMv8-A Process State, PSTATE
在ARMv8架构中,使用PSTATE用来描述当前处理器的状态信息。如下的图描述了PSTATE的每个字段的意义上面是PSTATE的各个bit位的含义,我们可以将其分为三组状态标志位 N Z C V 异常状态控制位 SS IL nRW EL SP 异常屏蔽位 D A I F 下面来详细描述下各个字段的含义:状态标志位 N(...
2020-03-30 17:55:59 7775 1
原创 ARMv8-A vs ARMv7 Registers
ARMv8-A General-Puspose RegistersARM8v-A提供了31个通用寄存器,分别是X0-X30。每个寄存器是64bits,可以在任何Exception Level访问。可以看到ARMv8-A总共提供了31个通用寄存器,分别为X0-X30。其中X29是栈帧寄存器,X30是LR链接寄存器。因为ARMv8-A为了兼容32位应用程序,所以放ARMv8-A中运行3...
2020-03-29 13:47:48 1267
原创 ARMv7 Processor modes
在ARMv7中定义了不同的特权级别。分别是PL0, PL1, PL2。而每种特权级别依赖处理器模式Processor modes在ARMv7中定义了九种不同的处理器模式User:就是所谓的用户模式,所处的级别最低,不能访问系统的所有资源。特权级别属于PL0FIQ:Fast IRQ,快速中断模式,特权级别属于PL1IRQ:中断模式,特权级别属于PL1Supervisor...
2020-03-27 17:29:37 3834
原创 ARMv8-A Exception Levels
在ARMv8中首次引入了Exception Level的概念,每个Exception Level代表了不同的特权级别。当然了ARMv7也存在同样的特权级别,只不过名字是用PL定义的。先来看下ARMv8的Exception Level的定义:ARMv8将特权级别分为4个level,分别是EL0,EL1,EL2,EL3。而每个level的特权不一样的,特权大小EL0<EL1...
2020-03-21 15:08:29 5741
原创 ARMv8-A architecture overview
从今天起,正式学习ARMv8-A架构的知识,其中会涉及到ARMv7-A的一些知识,用来和ARMv8-A做对比使用。学习过程中使用的文档:ARM Architecture Reference Manual for ARMv7, ARMv8 ARM Cortex-A75, A76 Core Technical Reference Manual(TRM) https://develop...
2020-03-20 18:32:21 2298
原创 Android tombstone文件是如何生成的
本节内容我们聚焦到androidQ上,分析android中一个用于debug的功能,那就是tombstone,俗称“墓碑”。现实生活中墓碑一般是给死人准备的,而在android系统中“墓碑”则是给进程准备的。为何Android要设计出这样一个东西呢? 因为android系统是运行在Linux Kernel内核之上的,当内核出现异常,则内核异常机制会分辨出是什么原因,处理不了的直接panic。而...
2020-03-14 14:44:08 12919 1
原创 NULL指针的奇妙之旅
今天带大家了解下NULL指针是如何形成的? 当然了我们要深入到操作系统中去看看为何访问一个NULL指令会报Segment Fault的错误。想必大家在接触计算机时都写过NULL指针的程序,尤其是玩C语言的小伙伴们。比如刚初始化的一个int类型指针,还没有赋值的时候就往这个指针赋值,然后运行就会出现Segment Fault的错误。#include <stdio.h>int...
2020-03-11 16:55:56 1268
原创 CFS调度主要代码分析二
在上一篇文章中我们分析CFS的主要代码,设计的内容有:进程创建时调度器是如何初始化一个进程的 进程是如何添加到CFS运行队列中 当进程添加到CFS运行队列中,是如何选择下一个进程运行的本节在围绕一个进程的生命周期,继续分析一个进程是如何被抢占? 如果睡眠? 如何被调度出去的?Schedule_tick(周期性调度)周期性调度就是Linux内核会在每一个tick的时候会去更新当前进...
2020-03-07 19:39:16 678
原创 CFS调度主要代码分析一
在前面学习了CFS调度的原理和主要的数据结构,今天我们就来进入代码分析环节。当然了代码分析只看主要主干不看毛细,同时我们也是根据一个进程是如何被调度的思路来分析一些重要的代码。在分析代码之前,有一些小函数需要先分析下,俗话说万丈高楼平地起,这些小函数还是很重要的。calc_delta_faircalc_delta_fair函数是用来计算进程的vruntime的函数。在之前CFS原理篇了...
2020-03-01 14:49:04 1673
原创 CFS 调度器数据结构篇
在上一节我们了解了CFS的设计原理,包括CFS的引入,CFS是如何实现公平,CFS工作原理的。本小节我们重点在分析CFS调度器中涉及到的一些常见的数据结构,对这些数据结构做一个简单的概括,梳理各个数据结构之间的关系图出来。调度类CFS调度器是在Linux2.6.23引入的,在当时就提出了调度类概念,调度类就是将调度策略模块化,有种面向对象的感觉。先来看下调度类的数据结构,调度类是通过str...
2020-02-28 18:53:05 1033
原创 CFS Scheduler(CFS调度器)
前面我们分享了O(n)和O(1)调度器的实现原理,同时也了解了各个调度器的缺陷和面临的问题。总的来说O(1)调度器的出现是为了解决O(n)调度器不能解决的问题,而O(1)调度器在Linux2.4内核的在服务器的变形是可行的,但是Linux2.4以后随着移动设备的逐渐普遍,面临的卡顿问题逐渐明晰,这才导致后来的CFS调度器的出现。今天我们来学习CFS调度器,再分析代码之前,我们可以先看下内...
2020-02-27 18:15:21 1977
原创 Linux O(1)调度器
前面我们学习了O(n)调度器的设计,以及它的核心算法。在这里复习下。O(n)调度器核心:O(n)调度器采用一个runqueue运行队列来管理所有可运行的进程,在主调度schedule函数中会选择一个优先级最高,也就是时间片最大的进程来运行,同时也会对喜欢睡眠的进程做一些补偿,去增加此类进程的时间片。当runqueue运行队列中无进程可选择时,则会对系统中所有的进程进行一次重新计算时间片的操...
2020-02-23 13:11:07 1487
原创 Linux O(n)调度器
前面我们学习了调度器的设计需要关注的几个点,在这里复习下:吞吐量(对应的是CPU消耗型进程) 响应速度(对应的是IO消耗型进程) 公平性,确保每个进程都可以有机会运行到 移动设备的功耗Linux中调度器的设计,引入的概念普通进程和实时进程使用优先级区分,0-99表示实时进程,100-139表示普通进程 实时进程采用两种调度策略SCHED_RR或者SCHED_FIFO 普通进程采...
2020-02-21 18:32:08 980
原创 进程调度开篇
在前面的几篇文章中,我们重点分析了如果通过fork, vfork, pthread_create去创建一个进程或者线程,以及后面说了在内核层面do_fork的实现。目前为止我们已经了解到一个进程是如何创建的。既然创建了一个进程,那这个进程肯定要去运行,执行它的使命。而进程何时被执行,在计算机系统中需要调度器来选择。所以我们从今天要开启一系列调度相关的知识了。为何要有调度器计算机设...
2020-02-20 18:32:40 506 1
原创 do_fork实现--下
昨天在do_fork实现–上中学习了do_fork创建的前半段,今天我们接着继续分析copy_Process函数分析了copy_fs, copy_files, copy_signal, copy_sighand, copy_mm,今天接着分析copy_thread, copy_thread是和架构相关的,需要到具体的ARCH目录下去看在分析copy_thread之前,我们先看几个知识...
2020-02-19 20:14:49 1245
原创 do_fork实现--上
在前面几节中讲述了如何通过fork, vfork, pthread_create去创建一个进程,或者一个线程。通过分析最终fork, vfork, pthread_create最终会通过系统调用clone去创建进程。今天我们就重点来分析clone之后的事情。为了学习今天这一节,前面的都是铺垫。既然fork, vfork, pthread_create都去调用到clone这个系统调用,...
2020-02-18 20:06:05 610
原创 Linux0号进程,1号进程,2号进程
本节我们将从linux启动的第一个进程说起,以及后面第一个进程是如何启动1号进程,然后启动2号进程。然后系统中所有的进程关系图做个简单的介绍0号进程0号进程,通常也被称为idle进程,或者也称为swapper进程。0号进程是linux启动的第一个进程,它的task_struct的comm字段为"swapper",所以也成为swpper进程。#define INIT_TASK_CO...
2020-02-17 20:07:26 9036 6
原创 ThreadInfo结构和内核栈的两种关系
本来本节是要学习内核启动的第一个进程的建立,也就是0号进程,也称idle进程,也称swapper进程。但是在学习第一个进程建立之前需要先学习threadinfo和内核栈的关系。目前内核存在两种threadinfo和内核的关系,接下来我们通过画图一一举例说明。ThreadInfo结构在内核栈中Threadinfo结构存储在内核栈中,这种方式是最经典的。因为task_struct结构...
2020-02-16 18:53:19 2772 4
ARMGIC手册详解.zip
2020-03-21
ARM_v8_architecture参考手册.zip
2020-03-21
ARMv8-A_Architecture.zip
2020-03-21
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人