操作系统篇-进程管理和中断
以下针对java来说明1. 进程 线程 纤程进程和线程区别进程就是一个程序运行起来的状态,线程是一个进程中的不同的执行路径。进程是OS分配资源的基本单位,线程是执行调度的基本单位。分配资源最重要的是:独立的内存空间,线程调度执行(线程共享进程的内存空间,没有自己独立的内存空间)线程在Linux中的实现《Linux内核设计与实现》第三版28页线程在Linux就是一个普通的进程,只不过和其他进程共享资
以下针对java来说明
1. 进程 线程 纤程
进程和线程区别
进程就是一个程序运行起来的状态,线程是一个进程中的不同的执行路径。
进程是OS分配资源的基本单位,线程是执行调度的基本单位。分配资源最重要的是:独立的内存空间,线程调度执行(线程共享进程的内存空间,没有自己独立的内存空间)
线程在Linux中的实现
《Linux内核设计与实现》第三版28页
线程在Linux就是一个普通的进程,只不过和其他进程共享资源(内存空间,全局数据等)
其他系统都有各自所谓的LWP的实现 Light Weight Process(轻量级进程)
纤程
即:用户空间的线程
为什么需要纤程:
java启动线程,在操作系统级别,就是启一个LWP。这是重量级线程。因为java启动线程需要向操作系统申请资源,和操作系统内核打交道,需要系统调用。
而纤程是线程中的线程,对应图最上面蓝色框,在用户空间,不需要向操作系统申请。
纤程处于线程内部,非常轻量级,可以在线程中快速切换。JVM自己管理,自己实现调度,自己切换,与操作系统无关。
纤程优势:
- 占有资源很少 OS : 线程:1M vs Fiber:4K
- 切换比较简单
- 启动很多个10W+
纤程的应用场景:
很短的计算任务,不需要和内核打交道,并发量高
2. 进程
Linux中也称为task,是系统分配资源的基本单位
资源包括:独立的地址空间,内核数据结构(进程描述符…),全局变量, 数据段…
Linux进程描述符:PCB (Process Control Block),用于Linux的进程管理(线程有他的PCB)
僵尸进程
ps -ef |grep defunct (defunct表示无用的僵尸进程)
父进程产生子进程后,会维护子进程的PCB结构,子进程退出后,由父进程释放,如果父进程没有释放,那么子进程会成为一个僵尸进程(defunct)
孤儿进程
子进程结束之前,父进程已经退出,就会产生孤儿进程,孤儿进程会成为Init进程的子进程,由1号进程维护 (在图形化Linux中是1457号线程)
调度策略
早期Linux 2.5 内核用的是Unix O(1)调度策略,按固定的时间片给程序
Linux内核2.6.23 采用CFS调度策略:Completely Fair Scheduler
按优先级分配时间片的比例,记录每个进程的执行时间,如果有一个进程执行时间不到他应该分配的比例,优先执行。 (比如有的程序开始没做什么就会让出给其他程序,当开始需要做的时候,优先执行)
默认调度策略:
实时进程 > 普通进程
实时进程优先级分高低 - FIFO (First In First Out),优先级一样的时候 - RR轮询(Round Robin)
普通进程: CFS
其中等级最高的是FIFO,这种进程除非自己让出CPU否则Linux会一直执行它,除非更高级的FIFO和RR抢占它
RR只是这种这种进程中是同级别FIFO中的平均分配 ---- 比如FIFO中有两个都是90优先级的进程,这时候按照RR执行。
只有实时进程主动让出,或者执行完毕后,普通进程才有机会运行。
3. 中断
硬中断
硬件和操作系统通信的一种机制
执行过程:
键盘 -----中断控制器(通知cpu一个中断信号来了)--------cpu(在内存中固定位置找处理程序)-------执行程序(查中断向量表,把中断信号给kernel)-------kernel(根据中断信号找程序)----------中断处理程序(已经写好的一堆处理程序,有处理键盘的,有处理打印机的)-----------------先由OS内核处理(上半场)------------再由应用程序处理(下半场)
软中断(80中断)
中断向量表特殊的符号
系统调用:int 0x80 (INT是用于x86处理器的汇编指令) 或者 sysenter原语(现在的cpu在硬件级别直接支持,汇编码)
通过ax寄存器填入调用号(比如1代表exit函数,2代表fork函数)
参数是通过bx cx dx si di传入内核
返回值通过ax返回
系统调用实现的hello world代码:
;以下例子主要调用了内核空间的write函数
;write(int fd, const void *buffer, size_t nbytes)
;fd文件描述符,buffer要写的内容,nbytes内容的长度
.section .data ;数据段声明
msg:
.ascii "Hello world!\n"
.section .text ;代码段声明
.globl _start ;指定入口函数
_start: ;在屏幕上显示一个字符串
movl $4, %eax ;系统调用sys_write
movl $1, %ebx ;文件描述符1,std_out
movl $msg, %ecx
movl $13, %edx
int $0x80
movl $1, %eax ;系统调用sys_exit
movl $0, %ebx
int $0x80
系统调用是通过int 0x80来实现的,eax寄存器中为调用的功能号,ebx、ecx、edx、esi等等寄存器则依次为参数,从 /usr/include/asm/unistd.h中可以看到exit的功能号_NR_exit为1,write(_NR_write)功能号为4,因此第一个int 0x80调用之前eax寄存器值为4,ebx为文件描述符,stdout的文件描述符为1,ecx则为buffer的内存地址,edx为buffer长度。第二个int0x80之前eax为1表示调用exit,ebx为0表示传入参数0。
注:eax 是32位的,ax是16位的
java中例子
java读网络 – jvm read() – c库read() - > 内核空间 -> system_call() (系统调用处理程序)-> sys_read()
更多推荐
所有评论(0)