自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(51)
  • 收藏
  • 关注

原创 深入探究Linux Kprobe机制

概述kprobe机制用于在内核中动态添加一些探测点,可以满足一些调试需求。本文主要探寻kprobe的执行路径,也就是说如果trap到kprobe,以及如何回到原路径继续执行。实例先通过一个实例来感受下kprobe,linux中有一个现成的实例:samples/kprobes/kprobe_example.c由于当前验证环境是基于qemu+arm64,我删除了其他架构的代码,并稍稍做了一下改动:/* * NOTE: This example is works on x86 and power

2020-11-08 11:19:02 927

原创 Linux exception table机制

概述简单来说,exception table用于截获一些异常,并且针对该异常做一些修正。一个简单的例子先来看一段调用逻辑及代码片段:futex_init futex_detect_cmpxchg(); cmpxchg_futex_value_locked(&curval, NULL, 0, 0) futex_atomic_cmpxchg_inatomic(curval, uaddr, uval, newval);ARM64平台:static in

2020-11-01 23:30:34 1397

原创 探究动态库函数的地址是在何时确定的

问题描述写了一段main函数:#include <stdio.h>#include <unistd.h>int main(int argc, char **argv){ printf("hello world\n"); printf("12345678\n"); _exit(0);}很简单,两条打印。但是printf属于glibc动态链接库,是在程序运行的时候再再加载链接进来的,那么这里的main函数是如何确定printf的地址的呢?从main函数的反汇

2020-09-06 14:57:36 976

原创 探寻main函数以外的大千世界

前言本篇文章并不探寻程序的本源,那是个庞大的话题,当然也是一个很吸引人的话题,但是本文并不打算谈论那些;本篇文章也不旨在解决什么实质性问题,因为据我多年工作经历来说,只了解main函数已经足够,至于main函数以外有什么,似乎无关紧要。我写下本片文章仅仅是因为一个我一直知道但是一直没有去了解的一个问题,linux下一个用户程序的起点在哪里?作为一个基于linux/uboot做驱动开发多年的老程序员来说,我当然知道main并不是唯一,不是起点,更不是终点,而仅仅是一个阶段,当然这是一个不可或缺的阶段。

2020-09-01 07:24:20 236

原创 一文讲透linux内核抢占

三种抢占模型概述在linux内核选项中存在存在三种抢占模型: │ │ ( ) No Forced Preemption (Server) │ │ │ │ (X) Voluntary Kernel Preemption (Desktop) │ │ │ │ ( ) Preemptible Kernel (Low-Latency Desktop) No Force

2020-08-09 00:05:44 1245

原创 时间子系统五——NO HZ浅析

这里首先要说一个tick这个概念,tick是分时操作系统的基础,主要用于多任务的切换。其实现原理就是起一个定时器,每隔固定的时间,就会超时一次,此时判断是否需要做任务切换,从而实现多任务分时复用CPU,超时时间由CONFIG_HZ来定义,如CONFIG_HZ=250则意味着每秒钟会发生250次ticks,也就是说定时器的超时时间是4ms。tick的发生实际上是由硬件定时器报中断到CPU,CPU做...

2020-03-01 22:31:34 1403

原创 时间子系统四——高精度定时器分析

本文简单解释一下高精度定时器的主要函数接口以及实现细节。hrtimer_init(struct hrtimer *timer, clockid_t clock_id, enum hrtimer_mode mode)高精度定时器的初始化,这里有两个参数要特别注意,clock_id和mode,其中clock_id指定基于哪一个时间域来做定时,一般来说有两个选择CLOCK_REALTIME和...

2020-02-16 12:38:58 485

原创 时间子系统三——低精度定时器和高精度定时器

先有低精度定时器,后来引入了高精度定时器。低精度定时器只能提供毫秒级别的定时时间,因为它实际上是依赖于jiffies的,一个jiffies的时间,就是其能够提供的最小定时时间,比如CONFIG_HZ配置为250,那么一个jiffies就是4ms,所以低精度定时器的精度就是4ms;而高精度定时器则不一样,它不依赖于jiffies,甚至jiffies是依赖于高精度定时器的,因为jiffies的累加实际...

2020-02-16 11:20:37 1056

原创 时间子系统二——clockevent之tick

简述clockevent的一个重要应用场景就是用于处理tick事件,在clockevent device之上,抽象出了一个tick device,分别用于维护clockevent的上下文和tick device上下文。clockevent和tick device的注册clockevent devicestruct clock_event_device { void (*event...

2020-01-12 00:17:39 630

原创 Linux时间子系统一——时间子系统综述

硬件timerTimer在硬件上是一个非常简单的东西(这里不考虑虚拟化,安全相关的问题),一般来说timer都会支持两种模式,一是periodic模式和free running模式,前者周期性的产生中断,后者一直往前累加到配置的最大值,报一次中断,称为one shot。软件抽象软件上将timer抽象成clocksource和clockevent,从名字大概就猜得出来,clocksourc...

2020-01-11 21:53:04 553

原创 Linux内存管理之揭开mmap的神秘面纱

前言我们首先来看一幅图Linux内存管理的最底层是buddy内存管理方案,也就是我们常说的伙伴算法,管理伙伴算法我们不做详诉,有兴趣的可以自行百度,我们这里只要知道buddy内存池中只能分配2^n个page的内存,比如1,2,4,8……个pages,然而正常使用的时候不会碰巧就需要1,2,4,8……个pages。所以基于buddy内存池,还需要有上一级的内存管理系统,内核里面采用的是slab...

2019-09-02 00:32:26 1431 2

原创 Linux elf文件的加载过程分析

前言在linux shell命令行启动一个程序时,实际上新启动的进程是作为shell进程的子进程存在的。shell进程会先fork出一个子进程,此时子进程是父进程的一个拷贝,所以其代码段和数据段都来自于父进程,但是子进程是要执行新的程序的,所以会调用execv函数,载入新的程序,此过程中,子进程的代码段,数据段等都会替换成新的进程的。本文主要是对elf文件的加载过程做一个简要的分析。lin...

2019-08-10 20:08:32 1827

原创 Linux内核各个段的权限设置

前言MMU除了管理虚拟地址到物理地址的映射外,还管理的访问权限。Linux内核分了很多段,如代码段,只读数据段,数据段等,不同的段访问权限肯定是不同的。代码段一般来说可读可执行,并且只能在特权模式下执行,但是不可写;只读数据段只能读,不能写也不能执行;数据段可以读写,不能执行。本文主要就是来介绍下linux内核各个段的权限设置问题,关于用户进程各个段的权限设置会在另外一篇文章中介绍。Linu...

2019-08-05 00:01:51 2686 2

原创 Linux内核调用栈一————原理介绍

前言Linux OOPS信息有出问题时候的函数调用栈;研究Linux内核代码的时候,很多时候会通过dump_stack()来查看linux的函数调用栈。那么这些函数调用栈是如何获取的,本文旨在以ARM64为例,给出一个前因后果。APCS这个话题要从APCS说起,APCS的全程是ARM Procedure Call standard,即ARM程序调用标准。该标准定义了ARM平台下函数调用过...

2019-06-02 23:58:15 1705 1

原创 ARM64异常漫谈二——kernel_entry和kernel_exit

前言本文介绍kernel_entry和kernel_exit两个宏,这两个函数并不单单是从用户空间进入内核空间以及从内核空间退出到用户空间才会用到。所有的异常处理函数首先会调用kernel_entry保存现场,最后调用kernel_exit恢复现场。kernel_entry .macro kernel_entry, el, regsize = 64 sub sp, sp, #S_FRA...

2019-05-23 08:03:48 2903

原创 ARM64异常漫谈一:异常向量表

前言ARMV8的异常向量表较ARMV7的异常向量表有了很大的变动,但是实际上换汤不换药,做事情的方式变了,但是做的事情还是一样的。本文会详细介绍一下ARMV8的异常向量表。异常routing下面是异常发生时,exception level切换表:我们举两个例子来说明下:第一个红色框的内容表示:在此种配置下,EL0和EL1状态下产生的异步异常,会导致CPU进入EL1。第一个红色框的内容...

2019-05-21 23:30:17 4046

原创 Linux swiotlb技术解析

概述swiotlb技术是一种纯软件的地址映射技术,主要为寻址能力受限的DMA提供软件上的地址映射,听起来比较玄乎,实际上其原理非常简单。我们下面先来谈一下该技术提出的背景。我们假设一个64位系统,其内存的基地址是0x80000000,内存大小是4G,则内存的物理地址范围是0x80000000-0x180000000,同时该系统中某个外设的DMA只能按32 bits地址寻址,即寻址范围为0-0...

2019-02-20 23:22:44 12299 1

原创 谈一谈copy_from_user和copy_to_user

前言copy_from_user和copy_to_user这两个函数相信做内核开发的人都非常熟悉,分别是将用户空间的数据拷贝到内核空间以及将内核空间中的数据拷贝到用户空间。这两个函数一般用于系统调用中,前者将用户空间参数拷贝到内核,后者将系统用的结果返回到用户空间。用户空间和内核空间Linux将地址空间分为用户空间和内核空间,内核文档Documentation/arm64/memory....

2018-12-23 23:36:28 33534 1

原创 Linux+ARM64 系统调用

前言用户进程有用户态和内核态两种执行状态,用户进程可以通过系统调用陷入内核态,陷入内核态就意味着可以访问内核的资源。那么如何陷入内核态呢?一般通过同步异常操作来实现。ARM64专门定义了svc指令,用于进入同步异常,也就是说,一旦执行了svc指令,cpu立即跳转到同步异常入口地址处,从这个地址进入内核态。从glibc说起要了解系统调用的完整机制,我们可以从glibc入手,因为glibc...

2018-12-21 00:14:35 6789

原创 Linux进程管理之ARM64的三级调度域

基本原理schedule domain分为三个层次,从低到高依次为SMT,MC和ALL Cpu。SMT即single multi thread,level0调度域,同一个物理Core中的所有thread都在该调度域中;MC即multi Core,level 1调度域,同一个cluster中的所有物理Core中的CPU都在该调度域中;ALL Cpu,level2调度域,也是最高级别的调度域,该调...

2018-12-13 00:12:22 2690 1

原创 Linux进程管理之CPU启动相关的四大状态

前言在讲调度域的初始化之前我们不得不先说一下多CPU启动的一些基本知识点,不过我们的目的是聚焦于调度域,所以只会讲与调度相关的内容。possible,present,online和active四大状态分别记录在__cpu_possible_mask,set_cpu_present,__cpu_online_mask和__cpu_active_mask这几个变量中。下面四个函数用于设置这四个状...

2018-12-10 00:16:13 3684

原创 Linux调度器基础之SoC架构

前言在多CPU系统中,调度器需要统筹所有的CPU做进程调度。每一个CPU多维护一个调度队列,调度队列上是该CPU需要调度的进程。然而,有些CPU调度队列上的进程可能比较少,甚至空闲;而有些CPU调度队列上的进程可能比较多,这样就会导致有些CPU闲置,有些CPU繁忙。为了解决这种负载不均衡的状态,引入了负载均衡的概念,负载均衡的基本思路是,如果当前CPU发现本地调度队列上的进程非常少,或者空了...

2018-12-09 10:50:27 1319

原创 Linux SMP之双ARM64核的启动方案

前言Linux+ARM64下多核启动方案有两种,spin table方案和psci方案,spin table方案非常简单,是一种纯软件方案;psci方案需要硬件支持,并且双核启动只不过是整个整个psci方案中的一小块,psci方案相对比较复杂。本文只会详细介绍spin-table方案,并不涉及psci方案。说到启动方案,肯定要从bootloader说起,典型的bootloader如uboot...

2018-12-05 23:35:25 3301 1

原创 Linux CFS调度器之msleep

前言我们之前多次提到过睡眠的进程由于没有占用CPU资源,所以其vruntime会比较少,睡眠时间越长,vruntime越小。为了防止睡眠进程醒来后,独占CPU导致其他进程饿死,进程醒来后,会重新调整其vruntime值,使其既能够收到CPU的优待,又不至于导致其他进程饥饿。另外,由于之前只分析了CFS调度器相关的代码,所以本文涉及到具体调度器的时候,全部以CFS调度器为例。进程睡眠msle...

2018-11-29 00:22:36 665

原创 Linux CFS调度器之选择下一个需要调度的进程

前言CFS调度器选择下一个要执行的进程时,基本原则是选择vruntime最小的进程,vruntime小意味着应该受到CPU的优待。但是在某些情况下,会对该原则有所违背,比如某个进程睡眠了一段时间,时间到了以后理应尽可能快的被调度,这个过程可能会导致当前进程被抢占,好端端的被抢占了,CPU在补偿了刚刚醒来的进程后,理应再补偿下被抢占的进程。发生在进程唤醒过程中的抢占事件进程睡眠和进程唤醒的...

2018-11-26 01:08:11 775

原创 Linux CFS调度器之判断当前进程是否应该调度出去

前言之前有说到过,定时器会周期性的产生中断,在其中断处理函数中,会更新当前进程的时间信息,并依此判断是否抢占当前进程。不过当时只是简单的介绍说,如果当前进程用完了分给他的时间片,就需要被调度器调出出去,今天我们来分析一下细节。调度延时我们先来说几个基本概念,调度延时,最小调度粒度,以及调度延时进程数。1. 调度延时unsigned int sysctl_sched_latency =...

2018-11-24 23:26:51 332

原创 Linux CFS调度器之虚拟运行时间vruntime

CFS简介Linux中大名鼎鼎的CFS调度器是专门为普通进程设计的调度器,CFS调度器的核心是虚拟运行时间vruntime。虚拟运行时间一方面跟进程运行时间有关,另一方面跟进程优先级有关,总的来说,进程占用CPU时间越长,进程优先级越低,其vruntime就越大。vruntime越小,代表CPU对进程的宠幸越少,那么后续就需要优先宠幸它;反之,vruntime越大,代表CPU对进程的宠幸越多,...

2018-11-24 00:27:57 2957

原创 Linux进程调度时机

我们之前有分析过,update_process_times会判断当前进程的时间片是否用完,如果用完了会设置TIF_NEED_RESCHED,在合适的时机,调用schedule函数做实际的进程调度。进程调度的时机,主要分成以下四种:直接调用schedule间接调用schedule,如果msleep函数中断返回时检测TIF_NEED_RESCHED,如果设置则调用schedule系统调用返...

2018-11-18 08:08:53 1936

原创 进程调度之update_process_times

linux中众多进程可以同时执行,是因为采用了时间片轮转方案。每个进程都会分得相应的时间片,当前进程的时间片用完了,CPU就会停止执行当前进程,选择其他合适的进程执行。那么什么时候判断当前进程的时间片是否用完了呢?这依赖于系统timer,timer周期性的产生时钟中断,在中断处理函数中,会更新当前进程的时间等统计信息,并判断当前进程的时间片是否用完,是否需要切换到其他进程执行。这个工作由upda...

2018-11-16 23:22:56 2777

原创 Linux内核进程管理进程切换之context_switch

基本概念进程虚拟地址空间ARM64的地址空间分配如下:用户地址空间0x0000000000000000–0000ffffffffffffffff内核地址空间0xffff000000000000–0xffffffffffffffff每一个用户进程拥有自己独立的用户地址空间,但内核地址空间只有一个,所有进程共用。task_struct有两个成员mm和active_mm,用来描述进...

2018-10-31 00:11:08 1196

原创 Linux内核进程管理之进程ID

进程ID简介一个进程实体对应一个task_struct结构体,关于这个结构体后续的文章会有介绍,这里我们只需要知道通过该结构体我们可以获得该进程使用的所有资源信息。进程ID顾名思义就是进程的ID,一个进程有四种类型的ID,分别是:PID:用于唯一标记一个进程这句话在以前是完全无误的,但是现在还必须加上一个条件,那就是在一个命名空间内唯一标记一个进程。关于命令空间,下一个章节会有介绍...

2018-10-28 22:46:44 659

原创 current_thread_info在ARM32和ARM64平台的不同点解析

首先对current_thread_info不熟悉的同学可以先百度一下这是个什么东西?我们这里仅仅简单的提一下,current_thread_info用于获取当前进程的信息。ARM32平台相关定义#define THREAD_SIZE_ORDER 1#define THREAD_SIZE (PAGE_SIZE &lt;&lt; THREAD_SIZE_ORDER)union thr...

2018-10-20 10:49:23 2537

原创 文章管理 优雅的slab内存分配器(六)—— freelist

freelist是干嘛的?我们前面提到过freelist,只不过仅仅提到了freelist可以放在slab内部也可以放在slab外部,并没有提到freelist的具体作用。我们今天就来剖析一下freelist的作用。freelist的作用其实非常非常简单,就是记录slab中没有使用的object。这里有几个注意点:freelist实际上是一个数组,数组中存放未使用的object的...

2018-08-12 23:19:24 2177 1

原创 优雅的slab内存分配器(五)—— 鸡肋一样的colour机制

Colour机制的作用slab中的colour机制是利用slab的剩余空间,减少cache行冲突的一种机制。不过笔者分析来下,总体感觉colour机制的效果不明显,如同鸡肋,食之无味弃之可惜,好在colour机制并没有给slab带来更多的复杂度。在分析colour机制之前,有必要补充一下硬件cache的基础知识,请参考我的另外一篇博客:《系统加速利器Hardware Cache(一)——三...

2018-08-12 01:16:17 1182 3

原创 系统加速利器Hardware Cache(一)——三种类型的Cache

Hardware cache的目的Hardware Cache的是为系统加速而生的,这个是众所周知的事情。不过为了本文内容的完整性,我在此还是先将hardware cache的功能讲一下,不过我会尽量简短一点。cpu访问hardware cache的速度要远高于访问主内存的速度,为了加快系统运行速度,会将主内存的部分数据放在hardware cache中,这样cpu就不必每次都访问主内...

2018-08-06 23:40:09 1156

原创 优雅的slab内存分配器(四)——shared cache

Shared cache的作用是什么?shared cache实际上充当了cpu_cache与slab之间的缓存。当cpu_cache中的object用完了,可以先从shared cache中获取object,如果shared object中没有object,才会到slab中申请object;同样,当释放object时,如果cpu_cache已满,则会将object释放到shared cach...

2018-08-04 00:16:27 816

原创 优雅的slab内存分配器(三)——分配和释放内存(kmalloc/kfree)

代码架构kmalloc架构kmalloc |-----&amp;gt;return __kmalloc(size, flags); | |-----&amp;gt;return __do_kmalloc(size, flags, _RET_IP_); | | |-----&amp;gt;return __do_kmalloc(size, flags, _RET_IP_); ...

2018-08-03 00:37:03 972

原创 优雅的slab内存分配器(二)——slab初始化kmem_cache_init

slab内存分配器初始化有函数kmem_cache_init来完成,本文会详细介绍slab内存分配器的初始化流程。软件架构kmem_cache_init |-----&amp;gt;kmem_cache = &amp;amp;kmem_cache_boot; | 第一个kmem cache实例,静态定义,不过尚需必须要的初始化 |-----&amp;gt;kmem_cach...

2018-08-01 00:14:02 1736

原创 优雅的slab内存分配器(一)——slab内存分配器基础知识

slab内存分配器是linux内核中比较经典的内存分配器,目前已经被slub内存分配器取代了。不过为了致敬经典,更是为理解slub分配器做铺垫,我还是会从slab分配器讲起。为什么需要slab内存分配器?这个问题其实很好回答,之所以提出slab分配器,是因为buddy system只能按page对齐来分配内存。然而大多数情况下,需要的内存size都不是按page对齐的,如果直接通过...

2018-07-29 10:21:15 5850

原创 Buddy system之free_pages

释放pages的基础知识在“Buddy system基础 ”这篇文章中已经讲过了,这里主要分析释放pages的代码。代码框架free_pages |-----&gt;__free_pages(virt_to_page((void *)addr), order); | |-----&gt;__free_pages_ok(page, order); | | ...

2018-07-15 22:01:36 371

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除