我们编写的代码只是一个存储在硬盘里的静态文件,通过编译可执行的二进制文件,当运行这个文件时,会被装载到内存中,接着CPU会执行程序中的每一条指令,那么这个运行中的程序,就被称为进程
如果程序中存在读写硬盘文件的代码,那么执行该指令时,由于读写速度很慢,如果CPU要等待读写得到的数据的话,那CPU利用率就是非常低的,所以要想办法在等待时机内去做其他的事,而收到通知后再回来继续,这个通知就是中断
最基本的三个是运行-阻塞-就绪,除此之外还有创建和结束状态
一个完整的进程状态变迁是:
且通常情况下,如果阻塞状态的进程过多,会占用很大的物理空间,所以一般会将阻塞的进程的物理内存空间移出到硬盘,等需要的时候再从硬盘移入物理内存,这个状态就是挂起
,用来描述进程没有占用实际的物理内存空间的情况
进程在外存并等待某个事件的出现
进程在外存,但只要进入内存即立刻运行
导致进程挂起的原因:
操作系统允许一个进程创建另外一个进程,而且允许子进程继承父进程所拥有的资源
过程如下:
当子进程被终止,从父进程处继承来的资源会归还给父进程,而当父进程被终止时,子进程会被变为孤儿进程,会被1号进程收养,并且由1号进程对它们完成状态收集工作
终止进程的过程:
当进程在等待其余事件时,它可以采用阻塞语句将自己阻塞,而一旦被阻塞等待只能由另外一个进程唤醒
过程如下:
阻塞态无法自己唤醒自己,所以需要等待其他进程的唤醒
过程如下:
各个进程之间是共享CPU资源的,在不同的时候进程之间需要切换,让不同的进程可以在CPU执行,这个切换的过程就称为上下文切换
每个任务执行前,CPU需要知道任务从哪里加载,从哪里开始运行,所以操作系统需要帮助CPU设置好CPU寄存器
和程序计数器
程序计数器就是用来存储CPU正在执行的指令位置,或者即将执行的下一条指令位置,这些环境就是上下文
即在运行前必须依赖的环境
进程是由内核管理和调度的,所以进程的切换只能发生在内核态
所以,进程的上下文切换不仅包含了虚拟内存、栈、全局变量等用户空间的资源,还包括了内核堆栈,寄存器等内核空间的资源,通常把交换的信息保存在PCB
中,运行另外一个进程时就会把信息从PCB中取出,加载到CPU中
发生场景
为什么要有线程?那自然是进程有缺点需要满足
比如一个程序,如果有多个操作,例如视频对话,首先需要读取文件,然后再进行解压缩,最后再播放,如果视频比较大,就需要在IO读取部分耗时过久,如果每个进程各执行一个功能,又需要实现进程之间的通信,共享数据,所以会很麻烦,而且维护进程的系统开销比较大
所以为了让实体之间可以并发运行,而且共享相同的地址空间,人们就发明了一个新的实体,线程
,可以并发运行而且共享相同的内存空间
线程是进程当中的一条执行流程
每个线程各自有一套独立的寄存器和栈,这样可以确保线程的控制流是独立的,而且共享代码段,数据段,解决了通信和数据共享的问题
进程是资源分配的单位,线程是CPU调度的单位
进程拥有一个完整的资源平台,线程只独享必不可少的资源,如寄存器和栈
线程同样具有就绪、阻塞、执行三种基本状态,同样具有状态之间的转换关系
线程能减少并发执行的空间和时间开销
线程的创建耗时少,它不需要像进程一样再去创建需要的一些信息,比如内存管理、文件管理信息等,它们只需要共享这些资源即可
线程终止时间比进程快,因为释放的资源少
同一个进程内的线程切换比进程切换快,因为线程具有相同的地址空间,意味着同一个进程的线程都具有同一个页表,而进程切换的时候需要把页表给进行切换,页表切换的开销就会比较大
共享了文件和内存,线程之间就不需要通过内核传输数据了
操作系统的任务调度实际上调度的是线程,而进程只是给线程提供了虚拟内存和全局变量等资源
而线程独有的资源就是其栈和寄存器,如果是两个不同进程的线程切换,则和进程上下文切换一样,否则的话只需要切换私有数据,寄存器等数据
在用户空间实现的线程,不是由内核管理的线程,是由用户态的线程库来完成线程的管理
在内核中实现的线程,是由内核管理的线程
在内核中支持用户线程
本文作者:Malyue
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!