操作系统进程与线程

操作系统作为计算机硬件和用户(用户程序)的中间层,负责管理硬件资源和软件资源,协调程序对硬件的使用,相当于定义了一套访问规则,起到类似于协议的作用。

进程的定义

操作系统的并发特性,意思就是无论是单处理器或者多处理器,同一时间都存在多个正在运行的程序,即进程。一般意思上,可以简单的认为,所谓进程就是程序在数据集上的运行过程,作用当然是执行某个任务。所以也可以把程序和进程按照静态和动态两种概念分别,进程就是CPU按照程序内容在数据集上的一个调度过程。由此可知进程的内容。

进程的内容

进程表达的是任务执行的过程,这里的任务自然是程序段,任务所操作的数据也就是所谓的数据段,可以是本地的初始数据,或者远程数据、别的进程处理到一半的数据,总之只要保证数据结构一致性即可(这就是进程通信、资源管理那些内容了,所谓的互斥量、信号量和共享内存之类)。除了程序段、数据段外,还有一个标识进程唯一性的PCB,俗称进程控制块。

PCB

PCB(Process Control Block),进程的唯一性标识,多个进程的程序段可能相同,数据段可能相同,那满足内核分辨进程的责任就交给PCB来完成了(内核为什么要分辨进程,自然是因为进程是内核的资源分配和调度的基本单位,即便有了线程的概念,如果线程是属于用户空间的,对内核不可见,则对内核来讲处理器的调度仍然以进程为单位)。PCB中包含的内容很多,下面几个具有代表性的:

1.PID

进程标识符,在作业调度(选择待执行任务)之后,分配一个唯一的进程标识号,之后才进行PCB的申请、资源分配(程序、数据、内存....)、PCB的初始化、完成初始化的PCB放入就绪队列。所以可以说进程的PID作为起点,就像咱的身份证号码一样,陪伴走过一生,随时随地接受检查、验明正身(进程的调度、切换、销毁),甚至挂掉了都还存在(僵尸进程)。

2.进程当前状态

保存进程的当前状态

进程状态有:

就绪状态:进程已处于准备运行的状态,万事俱备,只欠处理机。在进程的调度状态中,处于这个状态的机会很多,相比较与阻塞状态来讲,很多,比如说分时系统中,根据时间片进行切换状态

运行状态:要资源有资源,要处理器有处理器,任务处于执行中

阻塞状态:可以是等待IO操作的完成,或者等待获取某个资源(处理器之外),由阻塞状态只能转为就绪或者结束,不能直接变为运行状态

结束状态:进程正常或者异常结束,返回资源给系统或父进程,保留结束状态信息。如果当前进程还有子进程在运行,则其子进程成为出名的孤儿进程,这些子进程全部交给init进程收养,由init进程等待这些子进程结束后,完成状态收集工作;如果当前进程结束后保留的状态信息,没有由其父进程收集清理的话,则成为僵尸进程

至于为什么进程结束后,没有清空全部信息,还要保留个状态信息,作用当然是反馈。就像多线程中的调用关系,把任务交给别的线程执行,即任务线程,原线程作为调用线程,总要根据收集到的反馈信息来检查任务执行的情况,更为一般的,在任务线程的执行过程中如果发现异常,也应该完成清理工作尽快将异常反馈给调用线程,而不是自己直接丢掉或处理掉(就像Java线程池中的拒绝策略DiscardPolicy、DiscardOldestPolicy,阻塞队列和线程池都满了后,直接丢掉任务,连个招呼都不打)。

避免僵尸进程常用的两个方法:

信号机制

在子进程退出时,发送信号给父进程,父进程在信号处理函数中wait处理子进程的状态信息

两次fork机制

对子进程再fork一次,将子进程任务交给下一级子进程中执行,退出上一级子进程,则下一级子进程的称为孤儿进程,交给init进程处理其状态信息

3.进程优先级

进程优先级作用很明显,自我感觉良好,自觉带有特权的进程在进程调度上优先于优先级比它低的进程

4.CPU现场

进程调度时,保护处理器中的缓存信息。其实线程也有自己的线程控制块,在进行线程切换时,也会记录处理器信息

引入线程

线程的概念可以理解为任务中的一个处理流,进程要完成的是一个完整的任务,线程则是该任务中的一个个小分支。最烂大街的例子就是一个界面窗口程序,既存在完成交互响应的线程,也存在等待IO操作的线程。

在进程中引入线程的概念,自然是为了弥补进程中存在的缺陷。线程相对进程的特点:

1.调度简单

进程作为资源分配的单位,有自己独立的进程空间,每次进程切换都需要保存环境信息,相对的线程切换,只需要保存处理器相关的信息即可,当然线程也有自己的一点空间,比如私有的程序计数器信息还是需要保存的。但是相对于进程切换而言已经很轻量级了,当然如果是不同进程内的线程切换,则等同于进程切换。

2.开销低

因为线程是共享进程的空间,所以创建线程相对于创建进程分配的资源而言,相当轻量级

3.提高并发程度

因为进程的目的是为了多道程序并发,提高处理器和内存的利用率,同样为并发,线程处于进程之中,可以看作为二级并发,就像一级页表如果太大的话,可以建立二级页表来优化,线程可以作为进程并发的再并发,当然线程还有一个很突出的有点就是线程间通信。

4.线程间通信

进程间通信的常用方式,共享内存、消息队列、管道等方式,因为进程都有自己的独立空间,所以如果采用共享内存的话,还需要特殊函数将一块内存映射到不同的进程中,而线程则具有天然优势(当然是同一进程内的线程),因为共享同一个资源空间嘛。

线程类型

线程类型可以说有三种,用户线程、内核线程以及混合线程

用户线程

在进程内部,由程序根据线程库而创建的线程,虽然是私造的,但是也可以完成并发的特性,甚至跟正常线程功能一样,创建和管理很方面,也可以自定义使用规则,总之就是自己掌控,想怎么整怎么做,只不过对内核不可见,在内核眼中,只有进程,调度的单位也就是进程,所以可能存在的问题就是,如果进程中一个线程执行中阻塞,则整个进程都被阻塞掉,因为对内核而言,执行中的线程就是当前进程,所以存在并发度不高的问题。

内核线程

内核线程说的很明显,就是由内核来创建的线程,再交给用户线程进行对应,由内核创建的线程自然是没问题的,管理调度都由内核完成,也就是说此时的调度单位是线程,用户空间中只需要使用内核线程对应的用户空间中的线程即可,但是副作用很明显,太奢侈,虽然并发度提高了,阻塞一个还有一个,但一个用户程序存在多个线程,每个程序都这样,内核吃不消。

混合线程

内核提供几个线程与用户空间的诸多线程对应,只需要提供少量的线程即可对应多个用户线程,至于用户程序中的线程则交给自己创建、管理,用的时候只需要对应内核线程即可。既满足了并发又可以由自己管理线程,所以很nice。

总结

进程的引入是为了多道程序并发,提高资源利用率,线程则可以看做在进程上又做了一层优化,提供了更轻量级的处理器调度。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值