
kernel
文章平均质量分 84
扫地聖
make your heart ...
展开
-
kernel调度(2)----主调度器和周期性调度器
进程切换的前提条件设置TIF_NEED_RESCHED的时机其实在任务做切换的时候,首先要判读task_struct 中的thread_info中的flag 变量是否设置了TIF_NEED_RESCHED这个标记,如果设置了,才有可能被切换,否则这个线程还会一直运行。下面是thread_info中的变量:那么在什么时候去设置这个标记呢?其实主要在以下时机进行:(1)scheduler_tick 时钟中断函数内设置这里以cfs调度为例,代码流程如下图所示,这里就不做详细的流程介绍了也就是在时钟中原创 2022-01-30 10:01:58 · 2246 阅读 · 0 评论 -
用芯探核读书笔记--第一章启动分析
第一章内核启动分析(1)内核启动的第一入口vmlinux(非压缩内核):arch/mips/kernel/head.S 中的 kernel_entry–>start_kernelvminuz(压缩内核):rch/mips/boot/compressed/head.S 中的 start 标号–>start_kernel(2)第一入口的作用1:具体 CPU 类型相关的初始化;2:设置主核协处理器 0 的初始 Status 寄存器;3,清零.bss 段(未初始化全局数据段,位于__bss原创 2021-11-22 09:29:25 · 1231 阅读 · 0 评论 -
kernel调度(1)----基本知识介绍
调度简介最近在学习linux 内核调度相关的知识,也看了好多文章,内核代码,下面就学习的内容做个梳理,有助于自己的记忆,可能有的地方自己理解不对,希望多多指教。下面就从几个基本概念开始。什么是调度有过点操作系统知识的人都知道,调度的工作主要就是完成操作系统内进程切换的过程,让多个进程多个任务可以轮流的使用cpu的资源。那么在这个过程中涉及到很多调度相关的概念。下面就从这些简单的概念开始调度的对象–线程进程和线程的概念这里就不再详细的说,大家都知道。其实在内核里面,对于调度来说是不分进程还是线程概念原创 2021-11-21 18:16:56 · 2354 阅读 · 1 评论 -
读书笔记(11)—— kernel 全局开关中断
全局开关中断特点:通过结合使用本地开关中断和自旋锁来实现主要API全局关中断:cli()全局开中断:sti()大读者锁是对读者自旋锁的改进,它将读者所使用的数据结构分开放到不同的cache上面,避免缓存颠簸。(缓存颠簸:)主要API读者加锁操作:br_read_lock()读者解锁操作:br_read_unlock()写者加锁操作:br_write_lock()写着解锁操作:br_write_unlock()与中断开关结合使用的:br_read_lock_bh()/br_read_原创 2020-12-25 09:25:49 · 634 阅读 · 0 评论 -
读书笔记(10)—— kernel 完成量
完成量完成量特点自旋锁信号量在内的各种锁类机制都有一个共同的特点即加锁者和解锁者必须是同一个进程,而完成量不同,A进程加锁,B进程解锁的同步原语操作,主要用于进程间通信。数据结构struct completion { unsigned int done; wait_queue_head_t wait;}其中done字段表示完成状态,wait字段代表等待队列。工作原理就是:A进程将done设置为未完成,然后将自己挂接到wait队列上并进入睡眠(类似于信号量的加锁操作down),B进程完原创 2020-12-24 10:34:31 · 254 阅读 · 0 评论 -
读书笔记(9)—— kernel RCU
RCU原理RCU特点:RCU全称Read Copy Update 读复制更新,是一种完全不同于锁的并发控制机制。主要保护的对象:动态申请的内存,即指针变量。是扩展性最好的并发控制机制。RCU主要适用于读者多,写着少的场景不像锁那样将进程串行化来保护资源,是允许进程并发的。在一些必须串行化才能保护临界区的场景RCU是不适合使用的。RCU只能保证每个读者读到的数据是有效的,但是不能保证每个数据是最新的。大量的copy数据,占用了大量的内存,极端情况下可能会出现OOM(out of memory)的原创 2020-12-24 10:27:41 · 1224 阅读 · 0 评论 -
读书笔记(8)—— kernel 互斥量
互斥量从功能上讲,互斥量等价于二值信号量。然而用信号量来做互斥量有点大材小用,并且由于信号量的内存足迹(Foot Print)比较大,不利于性能优化。因此,Linux-2.6.16 开始专门引入了互斥量 Mutex。其数据结构定义如下:struct mutex { atomic_t count;spinlock_t wait_lock;struct list_head wait_list;#ifdef CONFIG_MUTEX_SPIN_ON_OWNERstruct task_struct *原创 2020-12-24 10:19:08 · 253 阅读 · 0 评论 -
读书笔记(7)—— kernel 信号量
信号量Linux 内核中应用最广泛的同步原语除了自旋锁就是信号量(Semaphore)。可以说自旋锁和信号量在很大程度上是一种互补的关系,它们有各自适用的场景,两者的场景加起来基本上可以覆盖一切内核中的所有场景。信号量可以是多值的(多值信号量),当其为二值信号量(只有两个值)时,类似于锁:一个值代表未锁,另一个值代表已锁。其工作原理与自旋锁最大的不同在于:获取锁的进程(内核的一个执行路径),若不能立即得到锁,就会发生调度转入睡眠;另外的进程释放锁时,唤醒等待该锁的进程。前面已经说过自旋锁的使用的限制主原创 2020-12-24 10:18:03 · 522 阅读 · 0 评论 -
读书笔记(6)—— kernel 顺序锁
顺序锁读写自旋锁是对普通自旋锁的改进,它对锁的竞争者进行了区分,允许多个读者同时进入临界区。但是读写自旋锁并没有区分读者和写者的重要性(优先权),因此带来一个新的问题:大量的读者持有读锁的时候,写者可能需要等待很长时间,直到所有读者都退出临界 区以后才能得到写锁。顺序锁就是为了解决这个问题来设计的,它同样适合读者多而写者少的场景,但是赋予了写者比读者高的优先权。顺序锁的数据类型定义如下:typedef struct {struct seqcount seqcount; spinlock_t lock原创 2020-12-24 10:16:18 · 194 阅读 · 0 评论 -
读书笔记(5)—— kernel 自旋锁
自旋锁自旋锁 Spinlock 是 Linux 内核中使用最广泛的同步原语。具有以下基本特征:1,获取锁的过程(即上锁的过程)是自旋(自旋就是忙等的意思)的,不会引起当前进程睡眠和调度。也就是说,当前进程一直出于活动状态中。2,持有自旋锁的临界区中不允许调度和睡眠,因为一旦发生调度,临界区什么时候能够继续运行是不确定的(什么时候解锁是不确定的),这会导致其他竞争者死锁。因此,自旋锁的加锁操作会禁止抢占,解锁操作时再恢复抢占。也因此,自旋锁既可以用于进程上下 文,又可以用于中断上下文。自旋锁的主要用途原创 2020-12-24 10:14:25 · 583 阅读 · 0 评论 -
读书笔记(4)—— kernel 开关抢占
开关抢占开关抢占主要面向单处理器系统上的并发控制。单处理器上不存在真正的并发执行,宏观上 表现出来的并发实际上是交错执行的。单处理器系统上的并发主要是异常/中断和抢占导致的。 异常/中断具有高优先级,会打断当前上下文,转入另外一个上下文环境去执行另一个内核路径。即便没有异常/ 中断,进程也有优先级高低之分,高优先级进程抢占低优先级进程同样会导致内核执行路径的切换。不同的上下文之间如果存在共享资源,那么就必须进行并发控制。在不加控制的情况下,硬中断上下文可以抢占软中断上下文和任意进程上下文的执行,软中断上下原创 2020-12-24 10:13:25 · 291 阅读 · 0 评论 -
读书笔记(3)—— kernel每CPU变量
每CPU变量为了减少不必要的共享,从而减少不必要的并发控制达到增强内核的性能和稳定性。每 CPU 变量就是为了达到这种目的而设计的,每个 CPU 都拥有一个同名的本地变量副本。在概念上,每 CPU 变量类似于一个长度为 CPU 个数的普通数组,比如:current_task[NR_CPUS];每个 CPU 根据自己的编号引用数组里面属于自己的元素:CPU0 用 current_task[0],CPU1 用 current_task[1],CPU2 用 current_task[2],但是每 CPU原创 2020-12-24 10:12:28 · 1238 阅读 · 0 评论 -
读书笔记(2)—— kernel 原子操作
原子操作如果共享资源(临界区)非常小,小到只有一个变量的话,就可以不用重量级的加锁- 解锁操作,而是直接使用原子操作。原子操作意味着整个操作的执行过程是原子的,不可中断的。原子操作分为以下几种,下面一一介绍:(1)通用原子操作Linux 内核定义了 32 位的原子变量类型 atomic_t 和 64 位的原子变量类型 atomic64_t,另外还有 atomic_long_t,在 32 位内核中等价于 atomic_t 而在 64 位内 核中等价于 atomic64_t。其代码如下:typede原创 2020-12-24 10:10:59 · 1843 阅读 · 0 评论 -
读书笔记(1)—— kernel 屏障问题
内核中的同步和并发其实并发和同步是操作系统设计中的一个核心问题,随着CPU的发展,多核多线程已经成为了主流,因此并发和同步是操作系统和内核开发者必须面临的问题。其实并发包括两类:一类是真正的同时发生, 在宏观尺度和微观尺度上都是并行执行的,这是多核CPU多级流水的情况;另一类是时分复用导致的交错发生,并不是真正的并发。在宏观尺度上是并行 但在微观尺度上是串行,这是单核处理器,只有一个流水线在执行。不管是哪类并发,都存在一个共享资源(临界区)保护的问题。临界区保护通常采用的手段就是串行化,其中最常见原创 2020-12-24 10:09:21 · 789 阅读 · 0 评论 -
如何查看内核的调用栈
如何查看函数的调用栈也就是根据当前cpu内寄存器的值,如何反推函数的调用栈,这种调试方法在内核调试过程中是很常见的,也算是常用的技巧。这个在追查死机等问题,可以用的上。(1)通过ejtag来读取当前pc的地址以及sp,ra寄存器的信息首先,我们的机器起来以后,我们用ejtag调试工具查看一下当前的寄存器的内容如下:cpu0 -set#setzero:0x0 at:0x5400cce1 ...原创 2019-12-06 20:12:43 · 2607 阅读 · 0 评论 -
start_kernel()之page_address_init()函数
该函数初始化高端内存(High Memory)线性地址空间中永久映射相关的全局变量。所以在不支持高端内存即在没有配置CONFIG_HIGHMEM这个宏的时候,该函数是个空函数什么也不做,在ARM系统中,是没有高端内存相关的代码的,所以这个函数就是个空函数。在支持高端内存的体系结构中,page_address_init()函数初始化高端内存页表池的链表 struct list_head page...原创 2018-11-07 07:17:10 · 2170 阅读 · 0 评论 -
start_kernel()之lock_kernel()详解
最近在看内核的源码,看着看着就想将所看到的内容写下来,这样即加深了对代码的理解,同时也为后续学习这方面知识的人做了一些铺垫。在网上讲解内核的书或者博客很多,所以也希望自己通过自己的理解和学习来写属于自己的文章。所以决定从每一个主要的函数开始,我知道这条路将会很长,内核源码那么多,这是一个长期的过程。希望自己能够坚持下来,争取能够写到内核源码的最终一个函数。本文所讲的内容是针对linux2.6....原创 2018-10-31 08:05:04 · 1786 阅读 · 0 评论