相同点
- 用于实现多任务并发
- 在多任务环境下功能上并没有太多的差异
- 拥有实体,是系统独立管理的单独个体
- 子进(线)程在调度的时候竞争起来和他们的父亲平等
实现方式
进程是资源分配的基础单位,线程是系统调度的基础单位
可以认为进程是一个工厂,线程是在工厂中进行工作的工人,政府的调度自然是能够以工厂为单位的,但是能够在细分一些,精确到个人。
而分配资源的时候应当是分到工厂中,如同机器,车间等,因此线程想要有效,首先需要的肯定是一个进程,实际上这个进程和依附于他的线程是一个共存关系,因此我们其实也是可以称这个进程为父线程。
正因为如此,在多任务环境下,一个进程的终结并不会影响另一个进程的执行,但是对于多线程而言,如果父线程被终结了他的所有子线程里所应当的都要被终结,因为这个时候他们所依附的资源会被全部剥夺。
进程通过fork(),vfork()来实现申请,这两者的区别最主要在于子进程是否仍然使用父进程的资源空间。
线程通过pthread_create来进行申请。
多任务设计模式的区别
进程和线程一个非常大的差别在于他们的资源方式,除了vfork出来的进程,两个进程之间是不共用资源的,比如说客户机提交了一个工作来让你处理,你需要处理完了之后,再张开一个进程从而达到第一个进程仍然能够接受以后的请求的目的,形成这样一个流水线式的操作。这个时候两个操作部分拥有自己的独立空间就非常必要,而如果是多线程的话,因为是共用了资源,所以一旦父线程接受下一个部分的时候刷新了子进程所需要使用的变量,就会引发不可避免的错误。
但是实际上资源互不独立同样也有他的好处,这个在讲到通信方式的时候再提。
通信方式的不同
进程通信方式
- 信号量
- 共享内存
- 消息队列
- 信号
- 文件
- socket
- 有名管道
- 无名管道
线程通信方式
- 信号
- 互斥量
- 自旋锁
- 读写锁
- 条件变量
- 信号
有一点值得注意的是,进程和线程之间的信号不互通,也就是说不能够接受彼此的信号,只能够接受他们同族的
进程采用的方式要么需要切换内核上下文(因为所有的进程调度都必须是通过系统内核来实现的,这是需要一个切换到内核中的一个操作,从用户态陷入到内核态有非常大的时间浪费),要么是通过外设实现的,相对而言,线程的通信方式因为不需要内核切换(内核线程除外,实际上是每一个进程中必然有一个线程与内核线程相关联,但其实只是用户态的进程中的线程切换的化是没有问题的),所以通信速度相对更快,同时也兼容本身进程所支持的通信方式。
因此线程有13种通信方式而进程有8种
资源管理方式的异同
进程部分
进程本身是系统分配资源的基本单位,所以如果有多个进程之间要进行资源共享,只能够通过进程同步方式来进行共享,诸如共享内存和消息队列,至于这两个区别在这里就不详细去展开了
线程部分
线程之间的共享资源只需要直接使用全局变量即可,因为在创建线程的clone中已经指定了他们的内存,文件,文件系统和信号共享了。同时也可以通过使用malloc()来动态申请
同时我们可以明白一个地方,在面对一些我们想要在即使意外终止之后仍然可以健壮复原的内存的话,我们实际上是可以通过共享内存来进行实现的,因为共享内存在系统中是独立存在于进程与线程之外的地方,我们可以通过对共享内存部分进行加锁,在重新获得状态之后check共享内存即可重新恢复状态,但是问题也同样处在他的共享性上,因为这样的话,其实你的内存部分就会对于整个系统可见,其他进程也可以对你的数据进行覆写。
附图