qianyi

Results 91 issues of qianyi

## Critical Regions and Race Conditions Code paths that access and manipulate shared data are called **critical regions** (also called critical sections). ## 并发原因 - **Interrupts**— An interrupt can occur...

中断处理程序与其他内核函数的区别在于内核调用它们来响应中断,并且它们运行在称为中断上下文的特殊上下文中;中断上下午也称为原子上下文,中断上下文不可调度。 处理程序必须快速运行,以便尽快恢复执行中断的代码,提高系统响应。 ## 上半部和下半部 上半部通常是执行时间非常短,需要尽快完成。下半部是处理可以延迟的工作 ### 中断处理函数 **注册中断** ```C /* request_irq: allocate a given interrupt line */ int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void...

## 链表 ```C struct list_head { struct list_head *next struct list_head *prev; } ``` ### 初始化 LIST_HEAD_INIT ### 链表头 ```C static LIST_HEAD(fox_list) ``` 设置链表头并初始化。 ### 链表操作 1. 添加元素 ```C list_add(struct...

系统调用为用户态程序提供了与内核交换的接口。 一般的,用户程序通常与API打交道而非系统调用,如下图所示。 ![image](https://user-images.githubusercontent.com/8001473/124440949-c474c600-ddad-11eb-98ab-652b2755eb83.png) `POSIX` is composed of a series of standards from the IEEE that aim to provide a portable operating system standard roughly based on Unix. 可以将`POSIX`理解为规范系统调用和用户态API的标准。 ## 系统调用...

## Linux进程调度器 ### 调度策略 调度器的策略通常决定了系统的整体性能,并负责优化利用处理器时间。因此,它非常重要。 ### I/O-消耗型和CPU消耗型 前者花费大量时间等待和发生IO请求,通常运行时间很短。而CPU消耗型则是花费大量时间执行代码。对于CPU消耗型的进程,它们更倾向于不需要频繁切换执行,但执行时间需要比较长。 系统的调度策略必须满足两个冲突:快速进程响应(低延迟),最大的系统利用率(高吞吐率)。Linux尝试在这两者之间做一个平衡。 ### 进程优先级 基于优先级调度是一种常见的调度算法。Linux 内核实现了两个独立的优先级范围。 第一个是基于**nice**值,范围从-20到+19,默认值是0。nice值越高,优先级越低。通过nice值,可以控制进程的时间片。可以通过`ps -el`的NI列查看nice值。 第二个是实时优先级,范围是[0,99],与nice值相反,实时优先级值越大,优先级越高。所有实时进程的优先级都比普通进程高。 可以通过`ps -eo state,uid,pid,ppid,rtprio,time,comm`查看进程的实时优先级,“-”表示非实时。 ### 时间片 时间片表示一个进程直到它被抢占能运行多长时间的数值。 ## Linux调度算法 ### 调度类 Linux 调度程序是模块化的,使不同的算法能够调度不同类型的进程。这种模块化称为调度程序类,调度器类使不同的、可插入的算法能够共存,调度它们自己类型的进程。 CFS调度器是普通进程的调度类,叫`SCHED_NORMAL`,也叫`SCHED_OTHER`。CFS实现在`kernel/sched_fair.c`。 **公平调度**...

## 进程 进程是程序的运行态;包含各种资源,如文件,信号,内存等。线程(Threads)是内核的调度单位。 ### 进程创建 进程通过`fork`系统调用复制一份(除了`pending signals`)现有进程创建出来。`fork`会返回两次,一次在父进程中,一次在新生进程中。 在`fork`后,通常需要运行新的程序,这通过`exec`族函数来实现;`exec`会创建新的`address space`来加载新程序。 ### Copy-On-Write 传统行为上,一旦fork,父进程的资源都会拷贝一份给子进程,这太低效了。在Linux中,`fork`使得父子进程可以以只读方式共享资源,当写的时候会触发异常然后将对应数据拷贝一份。`fork`的唯一开销是父进程的页表也会复制一份。 #### Fork流程 `fork`实际上是调用`clone`系统调用传入不同的Flag,最终调用到`do_fork`,再调用`copy_process`: 1. 调用` dup_task_struct()`,给新进程创建新的内核栈 2. 然后检查新进程是否超过当前用户的进程数资源限制 3. `task_struct`中部分资源清理或设置为初始值,以此和父进程区分开 4. 子进程状态被设置为`TASK_UNINTERRUPTIBLE` 5. `copy_process()`调用`copy_flags()`更新`task_struct`的`flags`,代表超级权限的`PF_SUPERPRIV`被清理,表示没有调用exec的`PF_FORKNOEXEC`被设置 6. 调用`alloc_pid()`分配新的PID 7. 根据`clone()`传入的参数不同,来拷贝不同的资源...

## 什么是softlockup > softlockups are bugs that cause the kernel to loop in kernel mode for more than 20 seconds, without giving other tasks a chance to run. The current...

如下的测试代码 ```C #include #include #include #include #include #include #define NSEC_PER_SEC 1000000000UL static unsigned long long get_time_ns(void) { struct timespec ts; clock_gettime (CLOCK_MONOTONIC, &ts); return ts.tv_sec*NSEC_PER_SEC+ts.tv_nsec; } int main (void) {...

这里的物理内存初始化主要是想记录下汇编代码后(汇编中建立了idmap和将内核镜像映射到vmalloc区)C语言中对物理内存和内核镜像的页表建立。 ### 内存再映射--map_kernel()函数 ```C /* * paging_init() sets up the page tables, initialises the zone memory * maps and sets up the zero page. */ void __init paging_init(void) { pgd_t...

本次分析基于Linux 5.0. 从bootloader跳转到kernel,kernel对系统状态有一些约定。 1. 关闭所有DMA设备防止获取不了正确的数据 2. 通用寄存器传递的参数 - x0 设备树在内存中的物理地址 - x1 = 0 (保留,后面会用到) - x2 = 0 (保留,后面会用到) - x3 = 0 (保留,后面会用到) 3. CPU模式 - 屏蔽CPU上的所有中断,比如PSTATE寄存器的DAIF域 -...