cpuset参数说明 cpuset下面参数:-rw-r--r-- 1 root root 0 1970-01-01 19:15 cgroup.clone_children-rw-r--r-- 1 root root 0 1970-01-01 19:15 cgroup.procs-rw-r--r-- 1 root root 0 1970-01-01 19:15 cpu_exclusiv
几个调度器参数说明: 1. /proc/sys/kernel/sched_short_sleep_ns调度器在任务运行短暂峰值时总是试图避免唤醒idle cpu。如果任务平均峰值小于sysctl_sched_short_burst纳秒,并且睡眠平均时间大于sysctl_sched_short_sleep纳秒,那么此任务倾向被打包。提高这个值会导致任务更频繁被打包,有利于功耗,但是会损害性
perf工具使用 perf用法:1.编译perf:直接在android下执行make perf2.perf支持的命令如下:root:# perf usage: perf [--version] [--help] COMMAND [ARGS] The most commonly used perf commands are: annotate
优先级反转及解决方法探讨 1. 什么是优先级反转(Priority Inversion) 由于多进程共享资源,具有最高优先权的进程被低优先级进程阻塞,反而使具有中优先级的进程先于高优先级的进程执行,导致系统的崩溃。这就是所谓的优先级反转(Priority Inversion)。2. 产生原因 其实,优先级反转是在高优级(假设为A)的任务要访问一个被低优先级任务(假设为C)占有的资源时,被
一则利用内核漏洞获取root权限的案例 kernel 最近出了一个新的本地提权安全漏洞CVE-2013-1763,影响范围比较广泛,ubuntu,Arch,fedora都受到其影响,漏洞刚公布就有牛人发布了利用该漏洞获取root权限的攻击代码,下面会分析该代码是如何获取root权限的。首先对CVE-2013-1763这个安全漏洞简单介绍一下。1. 漏洞描述在net/core/sock_diag.c中,__sock_dia
linux tracepoint用法 在kernel中经常会看到trace_XX形式的函数,但是又找不到它的定义。这个其实是kernel的tracepoint,定义在include/linux/tracepoint.h中。#define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \extern struct tracepoint
binder驱动代码注释下 //将new_buffer插入proc 的allocated_buffers rb tree中static void binder_insert_allocated_buffer(struct binder_proc *proc, struct binder_buffer *new_buffer){struct rb_node **p = &proc->allocated_buf
binder驱动源码全注释上 本文主要是自己阅读binder驱动时的注释。大概会先描述下数据结构,然后贴上主要的代码部分。 //描述一个binder对象struct flat_binder_object { /* 8 bytes for large_flat_header. */ __u32 type;//binder类型,如BINDER_TYPE_BINDER __u32 flags;//只对第一
UEFI在高通平台实现 UEFI(Unified extensible firmware interface)统一的可扩展固件接口,是一种详细描述类型接口的标准。可扩展固件接口(Extensible Firmware Interface,EFI)是 Intel 为 PC固件的体系结构、接口和服务提出的建议标准。其主要目的是为了提供一组在 OS加载之前(启动前)在所有平台上一致的、正确指定的启动服务,被看做
selinux在android中用法以及内核中代码实现 selinux(security enhance linux)是由美国国家安全局开发的,用来进行强制访问控制,增强linux系统安全性。传统的linux访问控制采用的是DAC(Discretionary Access Control)模型,这里面主要用的是uid控制。在linux系统里,对于文件的操作,只有「所有者」,「所有组」,「其他」这3类的划分。文件所有者对文件有所有
slub分配器实现 slub分配器对外主要提供几个接口://创建一个高速缓冲区struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,unsigned long,void (*)(void *));//销毁高速缓冲区void kmem_cache_destroy(struct kmem_cache *);/
slub数据结构 手机测试过程中,发现某个场景下,手机会概率性死机,初步调试分析发现内核打开CONFIG_SLUB_DEBUG后,死机问题消失。最终经过分析定位确定内核某个模块使用内存时越界了一个字节,导致了kernel panic。这里面就涉及到了slub在内存中存储结构。 slub可以认为是一块内存,在内核中除了大块内存按页框从伙伴系统获取外,内核中还有大量频繁使用的数
linux待机流程 linux待机是通过上层应用往sysfs节点/sys/power/state中写入mem,从而执行整个系统的待机流程。待机过程首先是冻结用户进程,内核线程,workqueue,接着依次执行各种设备的suspend操作,最后cpu core进入low power模式,等待外部中断或者事件唤醒整个系统。恢复的过程跟待机过程刚好相反,首先cpu core收到中断后,唤醒cpu cor
arm 待机指令 WFI和WFE 百度百科上对于待机的解释:待机是将当前处于运行状态的数据保存在内存中,机器只对内存供电,而硬盘、屏幕和CPU等部件则停止供电。由于数据存储在速度快的内存中,因此进入等待状态和唤醒的速度比较快。对于手机而言,待机就是除了DDR保持低频刷新,维护DDR中数据以外,其他的外围设备都断电,cpu core也进入low power 模式,停止工作,等待外部事件唤醒。arm core进
linux CONFIG_DEBUG_OBJECTS 用法 该选项用来开启debugobjects模块,对应内核代码中的debugobjects.c,这个模块是个通用的调试框架,用来跟踪object的生命周期。kernel中已有的应用该功能的object有timer,workqueue等,当然自己也可以定义自己的模块使用这个调试功能。一个object有下面几种状态:enum debug_obj_state {ODEBUG_S
内核栈溢出保护 linux内核中有个编译选项CC_STACKPROTECTOR用来开启GCC的stack-protector功能,这个功能是在GCC4.1版本中引入,用来检测栈是否遭到溢出攻击。目前我们用的版本中开启了这两个选项CONFIG_CC_STACKPROTECTOR、CONFIG_CC_STACKPROTECTOR_REGULAR。编译器栈溢出保护原理:函数栈存储结构,从
linux module解析 内核模块操作主要在kernel/module.c中,首先我们看下几个主要的宏定义:module_init,module_exit。这两个宏定义取决于是否有定义MODULE,没定义的话,表示模块静态编译进内核中。我们看下宏定义展开后的表示。#define module_init(x) __initcall(x);#define __initcall(fn) dev
objdump用法 objdump是个gcc的工具,用于解析二进制目标文件。具体的用法可以man objdump查看。下面简单介绍几个常用的用法,以kernel ko文件为例:-d 反汇编mmc_block_test.ko: file format elf64-littleaarch64Disassembly of section .text:
cpu 拓补结构 1. 前言在“Linux CPU core的电源管理(1)_概述”中,我们多次提到SMP、CPU core等概念,虽然硬着头皮写下去了,但是蜗蜗对这些概念总有些似懂非懂的感觉。它们和CPU的进化过程息息相关,最终会体现在CPU topology(拓扑结构)上。因此本文将以CPU topology为主线,介绍CPU有关(主要以ARM CPU为例)的知识。另外,CPU topolo
linux cpufreq interactive调频代码实现下 上一篇文章简单介绍了cpufreq初始化过程,最后会调用到cpufreq_init_policy,在这里面会启动对应的governor。static void cpufreq_init_policy(struct cpufreq_policy *policy){ struct cpufreq_policy new_policy; int ret = 0; memcpy(&new_
linux cpufreq interactive调频代码实现 Android使用的调频governor都是interactive,我们就以interactive为例,看下整个调频的代码实现。我们沿着driver初始化往下分析代码流程,高通平台对应的驱动文件qcom-cpufreq.c。初始化首先调用:msm_cpufreq_register//依次初始化每个cpu suspend_mutex和device_suspended,注册驱动,最
linux cpufreq 调频实现 目前的cpu频率越来越高,但实际上大部分场景并不需要cpu一直工作在最高频率。因为cpu工作频率越高,功耗越大,尤其是对手机等移动设备,更需要降低功耗,延长手机电池使用时间。在linux中,通过cpufreq来实现频率的动态调节。1. 先直观看下cpufreq提供的功能。在/sys/devices/system/cpu/中定义了相关的接口,root:/sys
linux cgroups概念及用法 1.什么是cgroup?Cgroups 是 control groups 的缩写,是 Linux 内核提供的一种可以限制、记录、隔离进程组(process groups)所使用的物理资源(如:cpu,memory,IO 等等)的机制。最初由 google 的工程师提出,后来被整合进 Linux 内核。Cgroups 也是 LXC 为实现虚拟化所使用的资源管理手段,可以说没有 cgr
linux mount过程 接下来我们以ext4 文件系统mount过程为例,讲解下文件系统的几种数据结构之间的关联。如果linux版本有支持ext4 fs,那么在linux初始化时会调用static int __init ext4_init_fs(void),这个函数会通过register_filesystem(&ext4_fs_type)向系统注册ext4文件系统到全局file_systems结构中。
linux性能分析工具 参考资料:https://www.slideshare.net/brendangregg/linux-performance-analysis-and-tools/16-Analysis_and_Tools_strace_Operating
linux文件系统数据结构 /*super_block 超级块对象,存储文件系统的信息,通常对应于存放在磁盘特定扇区的文件系统超级块或者文件系统控制块。*/struct super_block {struct list_heads_list; /* 所有超级块链表 */dev_t s_dev;/* 设备标识符 */unsigned char s_blocksize_bits; //位标
CPU访问各个部件的延时时长 转载:http://www.lenky.info/archives/2012/07/1784对cpu访问操作时间有个大概认识,对性能优化以及效率能有个更清晰的认识,例如调度器负载均衡时优先在调度组内进行,然后才是调度域。被普遍引用得比较多的数据如下:L1 cache reference 0.5 nsBranch mispredict 5 nsL2 cache ref
lowmemkiller 分析 Android是一个多任务系统,也就是说可以同时运行多个程序,这个大家应该很熟悉。一般来说,启动运行一个程序是有一定的时间开销的,因此为了加快运行速度,当你退出一个程序时,Android并不会立即杀掉它,这样下次再运行该程序时,可以很快的启动。随着系统中保留的程序越来越多,内存肯定会出现不足,lowmemorykiller就是在系统内存低于某值时,清除相关的程序,保障系统保持拥有一定数量的空闲内存
中断不能睡眠/调度的原因 操作系统以进程为调度单位,以进程描述符管理进程,进程调度就是调度器在不同的进程栈中切换。中断运行在中断上下文,没有类似中断描述符的数据结构,另外一点,有些架构(如X86)中断运行在独立的中断栈中,如果发生调度之后,没办法再调度回来,调度器无法切换到中断栈。还有中断对时间的要求,效率的原因都不允许其睡眠。参考文章:http://kyang.cc/2016/08/2
linux 使用copy_from_user而不是memcpy拷贝用户空间数据原因 我们平时在内核中访问用户进程的地址的时候一般会用到copy_from_user,而不是用memcpy直接拷贝。为什么有这样的要求?另外在走读代码的时候发现有同事直接用了memcpy将用户空间数据直接拷贝到内核空间,但是并没有发现导致死机,这是什么原因呢?接下来我们从代码实现中找到问题答案。//这个函数首先检查用户空间地址范围是否满足要求,接下来再去调用__copy_fr
linux 内核同步 现在抢占式多核环境下,需要有同步方法来保证共享数据修改正确性。这些数据同步方法需要处理器的支持,简单的可以理解为锁总线,保护共享数据在同一时刻访问的排他性。linux内核提供了两种锁,原子锁和同步锁。原子锁指的是指令执行是以原子操作的方式,不会被打断,保证了临界资源的同步。原子操作支持两组操作,一组是针对整数类型,一组是数据位。针对整数类型,定义了专门的数据
linux 时钟定时器 linux系统有两个时钟:一个是由电池驱动的RTC,被称为硬件时钟,断电后还是继续计时。另一个是内核时钟或者软件时钟,软件根据时钟中断来计数,断电后不存在。时钟周期:晶体振荡器在1秒内产生的时钟脉冲个数。时钟中断:当时钟计数器减到0时就会产生一次中断。时钟中断频率(HZ):1秒内timer产生的时钟中断个数。jiffy作为全局
linux 进程状态 执行top后会显示进程状态process state,state有R, S, D, T, Z, X, PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 24456 1476 648 S 0 0.0 0:05.10 init 2 r
linux cfs负载均衡 前一篇文章介绍了RT调度器的负载均衡,CFS调度器负载均衡实现更复杂,下面将一步步介绍下CFS 普通进程的负载均衡。普通进程的负载均衡在以下情况下会被触发:1、当前进程离开TASK_RUNNING状态(进入睡眠或退出),而对应的run_queue中已无进程可用时。这时触发负载均衡,试图从别的run_queue中pull一个进程过来运行。调用的路径idle_balance->
linux 调度器负载均衡 每个cpu上都有一个运行队列rq,运行队列里面又具体再分成rt_rq、cfs_rq等,在运行的过程中每个cpu上面task数量是不同的,这个用负载来衡量。cpu上rq内task越多,代表这个cpu 负载越重。负载均衡就是用来将task均匀分布在每个cpu上,使每个cpu负载大致均衡,提升task相应速度。负载均衡中有两个主要的操作,pull和push。当本地rq上tas
linux 非实时性 linux是非实时操作系统,虽然支持RT调度策略,但是并非是硬实时系统。linux非实时性主要表现在下面几个方面:1. 虚拟内存管理,导致实际物理内存分配的滞后性;2.调度策略问题,实时调度策略不能立即抢占,一般要在中断返回,系统调用返回用户空间时通过检查need_resched标记,进行重新调度,或者进程主动放弃cpu时,调用schedule,抢占性不强。3.关中断处
linux rt调度器 RT(RealTime scheduler)实时调度器,对应用户设定的调度策略为 SCHED_FIFO/SCHED_RR。SCHED_FIFO 先进先出队列调度,高优先级任务一直运行,直到任务阻塞,或者主动退出,或者被更高优先级任务抢占。SCHED_RR 时间片轮转调度,每个实时任务划分一个时间片,时间片用完会切换到其他任务执行。进程几种状态表示:1.
linux cfs调度器 CFS(completely fair scheduler)完全公平调度器,对应应用设置的调度策略为SCHED_NORMAL/SCHED_BATCH。这种调度策略区别于实时调度,进程优先级低于实时调度进程,用nice值来表示进程的重要程度,nice值得范围-20~19,转换成优先级为100~140。应用程序有多种类型,cpu 消耗型,交互型,nice值一般也不同。cfs调度器如
linux 调度器分析 cpu也是一种资源,linux 调度器负责不同进程在cpu上面的运行。进程的调度时机发生在下面几种情况:1、进程状态转换的时刻:进程终止、进程睡眠;2、当前进程的时间片用完时(current->counter=0);3、设备驱动程序主动调用schedule,让出cpu4、进程从中断、异常及系统调用返回到用户态时;调度器实现主要在kernel/sched/core.c
linux schedule 数据结构 以3.10版本内核为例,linux为了提升多核调度的效率,每个cpu上都有一个runqueue结构,这样就避免了多核争抢同一个runqueue造成的瓶颈。在每个runqueue中,包含了多个调度类(sched_class)的runqueue,调度类下面的子类主要有cfs(完全公平调度器),RT(实时调度器),其他的子类使用不多。几个调度器子类间的优先级顺序:deadline cla
linux vmalloc分析 vmalloc是内核中使用到的内存分配函数,一般用来分配大块内存,这个函数得到的是连续的虚拟地址,物理上地址不连续。具体看内核实现:void *vmalloc(unsigned long size){return __vmalloc_node_flags(size, NUMA_NO_NODE, GFP_KERNEL | __GFP_HIGHMEM);}最
linux mmap内核实现 用户态mmap最终会调用kernel 系统调用,SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,unsigned long, prot, unsigned long, flags,unsigned long, fd, unsigned long, pgoff)接下来分析下函数实现过程。
linux mmap用法: mmap定义如下:#include void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);函数说明:将地址为addr,长度length的文件数据映射到进程空间返回说明:成功执行时,mmap()返回被映射区的指针。失败时,mm
sysctl命令 在内核开发调试中,有时想动态修改内核参数,可以使用sysctl命令。这个选项可以用来设置vm,调度器,net等配置,设置的参数信息在/proc/sys目录下。sysctl 选项-n:打印值时不打印关键字; -e:忽略未知关键字错误; -N:仅打印名称; -w:当改变sysctl设置时使用此项; -p:从配置文件“/etc/sysctl.conf”加载内核
malloc 实现过程分析二 当进程需要访问malloc分配的虚拟地址空间时,发现这段空间还未映射物理内存,于是会发生缺页异常,然后在内核中分配物理内存,建立页表映射关系;kernel/arch/arm64/kernel/entry.Sel1_da: /* * Data abort handling */ mrs x
malloc 实现过程分析一 malloc是个库函数,用来申请内存使用。函数原型void *malloc(size_t size)。这个函数在不同的c库有不同的实现方式,大致的实现过程相同,先尝试从c库中申请一段线性空间,当空间不足时会通过系统调用在内核申请一段线性空间。当进程需要访问这段地址时,linux通过缺页中断进入内核处理,再分配具体物理地址。malloc申请物理内存都是通过kernel的brk或者
cpu多核技术发展 linux scheduler中有调度域(sched_domain)和调度组(sched_group)的概念,用来做负载均衡计算使用,而该算法主要跟CPU核心的复杂度有关。下面就从简单到复杂依次介绍下cpu多核技术的发展。SMT(Simultaneous multithreading)同时多线程技术,单个处理器核心可以同时执行多个线程。CMP(Chip multiproce
linux free_pages 伙伴系统释放内存过程 free_pages是伙伴算法释放内存过程,有两种情形,一种是释放单个page到当前cpu cache区pcp中;另一种是将内存释放到伙伴系统中;具体看下面代码:void free_pages(unsigned long addr, unsigned int order){if (addr != 0) {VM_BUG_ON(!virt_addr_vali
linux top 详解 top - 19:27:59 up 81 days, 9:07, 39 users, load average: 0.08, 0.10, 0.13Tasks: 624 total, 1 running, 592 sleeping, 27 stopped, 4 zombie%Cpu(s): 0.0 us, 0.1 sy, 0.0 ni, 99.9 id, 0.0 wa,
linux vmstat 用法 转载 : http://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/vmstat.htmlvmstat 监视内存使用情况vmstat是Virtual Meomory Statistics(虚拟内存统计)的缩写,可实时动态监视操作系统的虚拟内存、进程、CPU活动。10.1. vmstat的语法 vmstat
linux kernel page分配实现二 linux系统经过长时间运行后,很难有太多free pages可供分配,这个时候分配内存只能走慢速分配方式,里面涉及到内存回收和紧缩;内存回收跟紧缩算法比较复杂,涉及内容比较多,将在后续逐个介绍;static inline struct page *__alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, stru
linux kernel page 分配实现一 linux内核中分配page的实现最终都是调用alloc_pages主要的实现函数在__alloc_pages_nodemask中,下面将重点介绍下这个函数的实现过程。/* * This is the 'heart' of the zoned buddy allocator. */struct page *__alloc_pages_nodemask(g
linux PAGE_POISONING用法 page poison,内存毒药,page free时给page填充特定字节0xaa,在page alloc时check page内容是否有非0xaa的字节,有的话,代表当前分配的page被其他page盖到,或者说这个page周边的page有发生内存溢出;代码实现在debug_pagealloc.c中的kernel_map_pages:kernel/mm/Makefile:obj-$(
linux内存相关proc文件解析 linux中内存管理相关的proc文件有meminfo,buddyinfo,pagetypeinfo,slabinfo,vmallocinfo;下面分别介绍下buddyinfo,pagetypeinfo,slabinfo;/proc/buddyinfolinux kernel伙伴系统是以order为单位管理内存分组;Kernel会以Order 0,1,2,3,4,5,6
linux内存管理模型 linux内存模型有三种:CONFIG_FLATMEM,CONFIG_DISCONTIGMEM,CONFIG_SPARSEMEM。具体定义在include/asm-generic/memory-model.h中;memory model针对的是物理内存的分布,主要涉及PFN跟page结构的转换;PFN是page frame number的缩写,所谓page frame,就是
linux内存管理数据结构 1.相关概念UMA(Uniform Memory Access): 一致性内存访问,所有CPU core访问内存速度一致;NUMA(Non Uniform Memory Access):非一致性内存访问,不同CPU访问不同的内存区域速度是不一样的;不同的CPU分别挂载了属于自己本地的内存,所以CPU访问本地内存速度最快,访问远端内存速度相对较慢;linux中将NUM
linux内存空间划分 1. 32位系统空间划分 通常32位Linux内核地址空间划分0~3G为用户空间,3~4G为内核空间。注意这里是32位内核地址空间划分,64位内核地址空间划分是不同的。 下图是32位线性地址空间划分:注意kernel中两个关键值得定义:TASK_SIZE: 用户空间范围最大值PAGE_OFFSET: 内核空间范围起始地址
linux内存管理-虚拟地址转换成物理地址的过程 我们知道一个虚拟地址要依次经过分段机制转为线性地址,再经过分页机制从线性地址转换为物理地址。虚拟地址是由段标识符:段内偏移来表示。linux为了便于管理,将所有段标识符都设置为0,这样段内偏移就相当于线性地址。之前简单了介绍了分段,分页的原理,接下来通过代码实例进一步加深对地址转换过程的理解:static unsigned long test_vaddr2paddr(unsig
linux内存管理-分页机制 分段机制将逻辑地址转换成线性地址后,还需要借助分页机制,将线性地址转换为物理地址; 内存分页管理机制的基本原理是将整个线性内存区域划分成4KB为单位的内存页面; 32位处理器可以支持的寻址空间为2^32 =4GB,以4KB作为一个页,称为page或者page frame(页框);那么4GB的空间,总共就有4G/4K =1M个页面,每个页面属性需要4字节,整个页表所占空间就需要4
linux内存管理-分段管理 内存的管理方式有分段管理和分页管理两种; 分段管理是从逻辑内存的角度来分的,就是将用户程序地址空间分成若干个大小不等的段,每段可以定义一组相对完整的逻辑信息; 分页是从物理内存的角度,将内存按页划分,便于减小内存碎片; 分段管理的由来: 最早的处理器存储空间较小,采用的是直接物理内存访问的方式,这种称为实模式;为了支持更大的存储器,在
linux 物理地址,虚拟地址,逻辑地址的区别 逻辑地址(Logical Address):包含在机器语言指令中用来指定一个操作数或一条指令的地址,每个逻辑地址都由一个段和偏移量组成,偏移量指明了从段开始的地方到实际地址之间的距离。由程序产生的与段相关的偏移地址部分。例如,你在进行C语言指针编程中,可以读取指针变量本身值(&操作),实际上这个值就是逻辑地址,它是相对于你当前进程数据段的地址,不和绝对物理地址相干;应用编程中,变量a,
proc/meminfo 文件内存详解 /proc/meminfo 解析:MemTotal:可用的总内存--总物理内存减去kernel 代码/数据段占用再减去保留的内存区,mem_init_print_info里面有具体计算方式;MemFree:完全未用到的物理内存 LowFree+HighFreeMemAvailable:MemFree+Active(file)+Inactive(file)-(wate