详解操作系统中进程与线程

你好!这里是风筝的博客,

欢迎和我一起交流。


进程的定义:
进程是具有独立功能的程序在某个数据集合上的一次运行活动,也是操作系统进行资源分配和保护的基本单位。
简单的说,进程是一个程序的一次执行的过程。

进程的属性:
1)动态性:进程具有生命周期,由创建而产生,由调度而执行,由事件而等待,由撤销而消亡。
2)共享性:同一程序同时运行在不同的数据集合上构成不同进程,即多个不同的进程可执行相同的程序。
3)独立性:进程有自己的虚拟空间、程序计数器和内部状态。
4)制约性:进程因共享资源或协同工作产生相互制约关系,造成进程进程执行速度的不可预测性。
5)并发性:多进程的执行在时间上可重叠,在单处理器系统中可并发执行,在多处理器环境中可并发执行。

进程的目的:
1)刻画程序的并发性
2)解决资源的共享性
可以说,进程是为了占有系统资源和实现系统并发性引入的。

进程的状态(Linux中):
1)运行态(TASK_RUNNING):进程当前正在运行,或者正在运行队列中等待调度(排队中)
2)等待态_可中断(TASK_INTERRUPTIBLE):进程处于阻塞(睡眠sleep,主动放弃CPU)状态,正在等待某些事件发生或能够占用某些资源。处于这种状态下的进程可以被信号中断。接收到信号或被显式地唤醒呼叫唤醒之后,进程将转变为运行态,继续排队等待调度
3)等待态_不可中断(TASK_UNINTERRUPTIBLE):此进程状态类似于可中断的阻塞状态,只是他不会处理信号,把信号传递到这种状态下的进程不能改变它的状态,即不可被信号所中断,不能被随便调度
4)停止态(TASK_STOPPED),即暂停状态,进程的执行被暂停,当进程受到SIGSTOP、SIGTSTP、SIGTTIN、SIGTTOU等信号,就会进入暂停状态,知道收到继续执行信号,转变为运行态,继续排队等待调度
5)僵尸态(EXIT_ZOMBIE):子进程运行结束,父进程尚未使用wait 函数族(如使用wait()函数)等系统调用来回收退出状态
注:
僵尸状态下的子进程已经放弃了几乎所有的内存空间,没有任何可执行代码,也不能被调度,仅仅在进程列表中(即task_struct)保留一个位置,记载该进程的退出信息供其父进程收集。即进程结束后,内存地址空间被释放、task_struct 成员被释放,但task_struct 这个空壳还存在,它就是僵尸,这个僵尸我们用kill 是杀不掉的。所以,一般在子进程结束后,我们会对其进行回收。回收的方法有三种:
1)谁创建谁回收,即用父进程来回收;
2)父进程不回收,通知内核来回收;
3)由init 进程来回收,当父进程先死掉,子进程成为孤儿进程,由 init 进程来认养;
当这三种条件都不满足时,比如父进程不去回收子进程,自己却未死掉,僵尸便会出现,这是非常棘手的,可以通过杀死父进程来杀死僵尸(不推荐使用);

进程映像:
1)进程控制块:存储进程的标志信息,现场信息和控制信息。创建是建立,撤销时回收
2)进程程序块:被进程执行的程序,进程一次运行所完成的功能
3)进程核心栈:存放中断/异常现场,保存函数调用的参数、局部变量和返回地址
4)进程数据块:进程的私有空间,存放各种私有数据,用户栈也在此开辟
可见,每个进程由上述四个要素组成。

进程的优点:
1)顺序程序的特点:具有封闭性和可再现性;
2)程序的并发执行和资源共享。多道程序设计出现后,实现了程序的并发执行和资源共享,提高了系统的效率和系统的资源利用率。
进程的缺点:
1)进程间内存无法共享(资源是私有的,如虚拟地址空间,文件描述符和信号处理等),通讯比较麻烦,导致多任务之间的协作麻烦
2)任务切换,即进程间上下文切换,系统开销比较大。(虚拟地址空间以及task_struct 都需要切换)
3)在创建或撤消进程时,系统都要为之分配和回收资源

所以,为了提高系统的性能,减少程序并发执行是所付出的时空开销,使得并发颗粒度更细、并发性更好,引入线程的概念。

线程的概念:
把进程的“独立分配资源”和“被调度分派执行”分离开来,前一项任务仍然由线程完成,作为系统资源分配和保护的独立单位,无需频繁的切换。后一项任务交给线程的实体完成,作为系统调度分派的基本单位,会被频繁的调度切换。

线程的定义:
线程是进程能够并发执行的实体,是进程的组成部分,也是多处理器调度和分派的基本单位。

线程的属性:
有状态及状态转换,所以需要提供一些状态转换操作
不运行时需要保存上下文环境,所以需要程序计数器等寄存器
有自己的栈和栈指针
共享所在进程的地址空间和其它资源

可以认为,线程基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),它与同属一个进程的其他的线程共享进程所拥有的全部资源,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位

线程的状态(Linux中):
运行态、就绪态、等待态、终止态
注:
线程不是自愿拥有单位,挂起态对于线程来说是没有意义的(进程挂起后被换出内存,线程因共享空间也必须对换出去,可见挂起操作所引起的状态是对进程级状态而不是线程级状态)

线程的优点:
1)快速线程切换:多线程切换只需改变堆栈和寄存器,地址空间不变
2)通信易于实现:共享进程的内存和文件,可自由访问全局变量而不必经过内核
3)减少管理开销:创建和撤销无需再分配存储空间各种资源
4)并发程度提高:适宜并行工作,使得多核和多处理器系统效能发挥更好
线程的缺点:
1)因为共享地址空间,如果其中一个线程出现错误(比如段错误),整个线程组都会崩掉!
2)调度时, 要保存线程状态,频繁调度, 需要占用大量的机时

.

进程与线程的区别:
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。
进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

最后,操作系统的设计,可以归结为三点:
1)以多进程形式,允许多个任务同时运行;
2)以多线程形式,允许单个任务分成不同的部分运行;
3)提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。

猜你喜欢

转载自blog.csdn.net/guet_kite/article/details/78604349