linux进程管理子系统分析,Linux进程管理子系统(国嵌学习笔记)

6>进程撤销

01a2aa47dbe771e5aea73760d855805e.png

进程销毁可以通过几个事件驱动--通过正常进程结束、通过信号或是通过对exit函数的调用。不

管进程如何退出,进程的节点胡都要借助对内核函数do_exit的调用。

二、Linux进程调度

1>调度:从就绪的进程中选出最适合的一个来执行。调度策略、调度时机、调度步骤。

2>调度策略

1)SCHED_NORMAL(SCHED_OTHER):普通的分时进程

2)SCHED_FIFO:先入先出的实时进程

3)SCHED_RR:时间片轮转的实时进程

4)SCHED_BATCH:批处理进程

5)SCHED_IDEL:只在系统空闲时才能够被调度执行的进程

6)调度类的概念:

CFS调度类(在kernel/sched_fair.c中实现)用于以下调度策略:SCHED_NORNAL、

SCHED_BATCH和SCHED_IDEL。

实时调度类(在kernel/sched_rt.c中实现)用于SCHED_RR核SCHED_FIFO策略。

pick_next_task:选择下一个要运行的进程

2>调度时机

调度什么时候发生即:schedule()函数什么时候被调用。调度的方式有两种:

1)主动式

在内核中直接调用schedule()当进程需要等待资源而暂时停止运行时,会把状态置于挂起(睡眠),并主动请求调度,让出CPU。

2)被动式(抢占)

用户抢占(2.4,2.6)

用户抢占发生在:

*从系统调用返回用户空间。

*从中断处理程序返回用户空间。

内核即将返回用户空间的时候,如果need_resched标志被设置,会导致schedule()被调用,此时就会发生用户抢占。

内核抢占(2.6)

*在不支持内很抢占的系统中,进程/线程一旦运行于内核空间,就可以一直执行,知道主动放弃或时间片耗尽为止。这样一些非常紧急的进程或线程将长时间得不到运行。

*在支持内核抢占的系统中,更高优先级的进程/线程可以抢占正在内核空间运行的低优先级进程/线程。

*在支持内核抢占的系统中,某些特例下时不允许内核抢占的:

1、内核正进行中断处理。

2、内核正在进行中断上下的Bottom Half(中断的底半部)处理。硬件中断返回前会执行软中断,此时任然处于中断上下文中。

3、进程正持有spinlock自旋锁、writelock/readlock读写锁等,当持有这些锁时,不应该被抢占,否则由于抢占将导致其他CPU长期不能获得锁而死等。

4、内核正在执行调度程序Scheduler。抢占的原因就是为了进行新的调度,没有理由将调度程序抢占掉再运行调度程序。

为保证Linux内核在以上情况下不会被抢占,抢占式内核使用了一个变量preempt_count,称为内核抢占计数。这一变量被设置在进程的thread_info结构中,每当内核要进入以上几种状态时,变量preempt_count就加1,指示内核不允许抢占。每当内核从以上几种状态退出时,变量preempt_count就减1,同时进行可抢占的判断与调度。

内核抢占可能发生在:

*中断处理程序完成,返回内核空间之前。

*当内核代码再一次具有可抢占性的时候,如解锁及使能软中断等。

3)调度标志(TIF_NEED_RESCHED)

作用:

内核提供了一个need_resched标志来表明是否需要重新执行一次调度。

设置:

当某个进程耗尽它的时间片时,会设置这个标志;

当一个优先级更高的进程进入可执行状态的时候,也会设置这个标志。

3>调度步骤

1)清理当前运行中的进程;

2)选择下一个要运行的进程;(pick_next_task)

3)设置新的进程的运行切换;

4)进程上下文切换。

三、Linux系统调用

1>定义:一般情况下,用户空间是不能访问内核的。它既不能访问内核中的数据,也不能调用内核中

的函数。但系统调用是一个例外。Linux内核中设置了一组用于实现各种系统函数功能的函数,称为

系统调用,用户可以通过系统调用命令在自己的应用程序中调用它们。

系统调用和普通的函数调用非常相似,区别仅仅在于,系统调用由操作系统内核实现,运行于内核

态;而普通的函数调用由函数库或用户自己提供,运行于用户态。

2>库函数

Linux系统还提供了一些C语言函数库,这些库函数对系统调用进行了一些包装和扩展。

3>系统调用数

在2.6.36/38版内核中,共有系统调用369个。可在arch/arm/include/asm/unistd.h中找到它

们。

4>工作原理

应用程序首先用适当的值填充寄存器,然后调用一个特殊的指令跳转到内核某一固定的位置,内核根

据应用程序所填充的固定值来找到相应的函数执行。

1)适当的值

在文件include/asm/unistd.h中为每个系统调用规定了唯一的编号,这个号称为系统调用号

#define __NR_restart_syscall (__NR_SYSCALL_BASE+ 0)

#define __NR_exit            (__NR_SYSCALL_BASE + 1)

#define __NR_fork            (__NR_SYSCALL_BASE + 2)

#define __NR_read            (__NR_SYSCALL_BASE + 3)

2)特殊的指令

在Intel CPU中,这个指令由中断0x80实现

在ARM中,这个指令时SWI(已经重命名为svc指令)。

3)固定的位置

在ARM体系中,应用程序跳转的固定内核位置是ENTRY(vector_swi)

4)相应的函数

内核根据应用程序传递来的系统调用号,从系统调用表sys_call_table找到相应的内核函数。

CALL(sys_restart_syscall)

CALL(sys_exit)

CALL(sys_fork_wrapper)

5>实现系统调用

向内核中添加新的系统调用,需要执行3个步骤:

1、添加新的内核函数

2、更新头文件unistd.h

3、针对这个新函数更新系统调用表calls.S

例:

1在kernel/sys.c中添加函数

asmlinkage int sys_add(int a, int b)

{

return a + b;

}/*asmlinkage:使用栈传递参数*/

2在arch/arm/include/asm/unistd.h中添加如下代码:

#define __NR_add    (__NR_SYSCALL_BASE + 370)

3在arch/arm/kernel/calls.S中添加代码,指向新实现的系统调用函数:

CALL(sys_add)

4重新编译内核

四、Proc文件系统

1>定义

proc文件系统是一种在用户态检查内核状态的机制。

通过/proc/meminfo,查询当前内存使用情况。

2>子目录/文件名

apm:高级电源管理信息

bus:总线以及总线上的设备

devices:可用的设备信息

driver:已经启用的驱动程序

interrupts:中断信息

ioports:端口使用信息

version:内核版本

3>特点

1)每个文件都规定了严格的权限

可读?可写?哪个用户可读?哪个用户可写?

2)可以用文本编辑程序读取(more命令,cai命令,vi程序等等)

3)不仅可以文件,还可以有子目录

4)可以自己编写程序添加一个/proc目录下的文件。

5)文件的内容都是动态创建的,并不存在于磁盘上。

4>内核描述

struct proc_dir_entry{

............................................

read_proc_t* read_proc;

write_proc_t* write_proc;

...............

1)创建文件:

struct proc_dir_entry* create_proc_entry(const char* name, mode_t mode, struct proc_dir_entry*parent)

功能: 创建proc文件

参数:

name:创建的文件名

mode:要创建的文件的属性 默认0755

parent:这个文件的父目录

}

2)创建目录:

struct proc_dir_entry* proc_mkdir(const char* name, struct proc_dir_entry* parent)

功能:

创建proc目录

参数:

name:要创建的目录名

parent:这个目录的父目录

为了能让用户读写添加的proc文件,需要挂接上读写回调函数:

read_proc

write_proc

3)读操作:

int read_func(char* buffer,char** stat, off_t off, int count, int* peof, void* data)

参数:

buffer:把要返回给用户的信息写在buffer里,最大不超过PAGE_SIZE

stat:一般不使用

off:偏移量

count:用户要取的字节数

peof:读到文件尾时,需要把*peof置1

data:一般不使用

4)写操作

int write_func(struct file* file,const char* buffer,unsigned long count,void* data)

参数:

file:该proc文件对应的file结构,一般忽略。

buffer:待写的数据所在的位置

count:待写数据的大小

data:一般不用

5>实现一个proc文件的流程

1)调用create_proc_entry创建一个struct proc_dir_entry.

2)对创建的struct proc_dir_entry进行赋值:read_proc,mode, owner,size,write_proc等等。

实例分析:

五、Linux内核异常

常在河边走,哪有不湿鞋,内核级的程序,总有死机的时候,如果运气好,会看到一些所谓"Oops"信

息。

Oops可以看成是内核级的Segmentation Fault。应用程序如果进行了非法内存访问或执行了非法指

令,会得到Segfault信号,一般的行为是coredump,应用程序也可以自己截获Segfault信号,自行处

理。如果内核自己犯了这样的错误,则会打出Oops信息。

分析步骤:

1、错误原因提示

2、调用栈(对照反汇编代码)

3、寄存器(pc)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目录 1 进程的组织 5 1.1 进程相关数据结构 5 1.1.1 进程的基本信息 6 1.1.2 进程状态 10 1.1.3 TASK_RUNNING状态的进程链表 11 1.1.4 进程间关系 12 1.2 Linux的线程——轻量级进程 15 1.3 进程的创建——do_fork()函数详解 19 1.4 执行进程间切换 33 1.4.1 进程切换之前的工作 33 1.4.2 进程切换实务 —— switch_to宏 37 1.4.3 __switch_to函数 39 1.5 fork与vfock系统调用的区别 42 1.6 内核线程 46 1.7 挂起状态进程的组织 49 1.7.1 等待队列头 49 1.7.2 等待队列的操作 50 1.7.3 进程资源限制 55 1.8 系统调用execve() 56 1.8.1 拷贝用户态参数 57 1.8.2 重要的数据结构 61 1.8.3 search_binary_handler函数 66 1.8.4 目标文件的装载和投入运行 69 1.8.5 库函数 92 2 中断控制 94 2.1 中断的分类 94 2.2 中断的硬件环境 95 2.2.1 外部中断请求IRQ 95 2.2.2 中断描述符表 96 2.2.3 中断和异常的硬件处理 97 2.3 中断描述符表 99 2.3.1 中断门、陷阱门及系统门 99 2.3.2 IDT的初步初始化 100 2.4 异常处理 101 2.5 中断处理 106 2.5.1 中断向量 107 2.5.2 IRQ数据结构 108 2.5.3 do_IRQ()函数 113 2.5.4 中断服务例程 115 2.5.5 IRQ线的动态分配 116 2.6 下半部分 117 2.6.1 软中断 118 2.6.2 tasklet 121 2.6.3 工作队列 122 2.7定时器中断 124 2.7.1 时钟与定时器 124 2.7.2 定时器中断相关的数据结构 127 2.7.3 定时器中断的上半部分 129 3 进程调度 138 3.1 进程调度的概念 138 3.2 进程调度的数据结构和优先级 141 3.2.1 进程的优先级 141 3.2.2 数据结构 145 3.3 调度程序所使用的函数 151 3.3.1 scheduler_tick函数 151 3.3.2 try_to_wake_up函数 156 3.3.3 recalc_task_prio函数 160 3.4 schedule()函数 163 3.4.1 直接调用 163 3.4.2 延迟调用 164 3.4.3 进程切换之前所做的工作 168 3.4.4 完成进程切换时所执行的操作 171 3.4.5 进程切换后所执行的操作 173 3.5 多处理器运行队列的平衡 175 3.5.1 调度域 176 3.5.2 rebalance_tick()函数 178 3.5.3 load_balance()函数 180 3.5.4 move_tasks()函数 183 3.6 进程退出 187 3.6.1 进程终止 187 3.6.2 进程删除 189 4 进程的并发性体现 191 4.1 内核抢占 193 4.1.1 内核抢占概念 193 4.1.2 同步技术总揽 196 4.2 每CPU变量 197 4.3 原子操作 199 4.4 优化屏障和内存壁垒 203 4.4.1 优化屏障 204 4.4.2 内存壁垒 204 4.5 自旋锁 206 4.6 读写自旋锁 211 4.6.1 为读获取和释放一个锁 213 4.6.2 为写获取或释放一个锁 214 4.7 顺序锁 215 4.8 RCU机制 217 4.9 信号量 219 4.9.1 获取和释放信号量 221 4.9.2 读/写信号量 224 4.9.3 补充信号量 225 4.10 禁止本地中断 226 4.10.1 禁止本地中断 227 4.10.2 禁止下半部(可延迟函数) 229 4.11 一些避免竞争条件的实例 231 4.11.1 引用计数器 231 4.11.2 大内核锁 231 4.11.3 内存描述符读/写信号量 232 4.11.4 slab高速缓存链表的信号量 233 4.11.5 索引节点的信号量 233 4.12 内核同步与互斥的总结 233

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值