• 计算机进程和线程的一些联系和区别
  • 发布于 2个月前
  • 64 热度
    0 评论

身为一名程序员,无论是搞前台还是后台,不可避免的就是与代码打交道,按照笔者原来的理解,代码是死的(静态的),一旦代码运行起来,就会产生进程(动态的),进程是系统分配资源的基本单位,线程是cpu调度的最小单位,一个进程可以有多个线程,每个进程有自己的文本区域,数据区域以及堆栈区,而线程除了一些必不可少的资源以外是共享进程的资源的。所以通过上面的简单粗略的定义,我们不难得到进程间由于拥有独立的资源一定存在相互通信的问题,而线程由于共享资源难免会面临相互间资源共享的问题。

但是面临上面的问题,笔者也只是有着大概的了解包括定义也是一样,于是通过学习,了解到除了进程、线程,还存在协程以及保护进程,那么接下来让我们对他们的定义、区别以及上面一段末尾的两个问题进行详细的介绍,一起学习下吧。

1.进程
进程是系统资源分配和调度的基本单位,每一个进程都有它自己的空间地址,其中包括文本区域、数据区域和堆栈。文本区域即用来存储执行代码的区域,数据区域用来存储变量以及动态分配的内存,堆栈用来存储执行的指令和本地变量(本地变量详解见最下面名词解释),进程不同于程序,像上面所说的那样,程序是静态的,当程序被处理器运行赋予生命时,就声称了一个进程,我们也管进程叫做实体。
2.线程
线程也叫轻量级进程(LWP),它是程序执行流的最小单元,一个进程可包含多个线程,如果一个运行的程序只有一个线程,那么这个线程就是程序本身。线程由线程id,指令指针(PC),寄存器和堆栈组成,但是值得注意的是,线程之间是共享进程资源的。线程也包含三种状态,运行态、就绪态和阻塞态。运行态即线程获得了cpu的使用权力,就绪态称作逻辑上的满足,即其它一切条件均满足只是缺少占用cpu的许可;阻塞态即逻辑上都不满足可能在等待某个事件(如信号量)。
3.协程
不同于线程,线程间是相互独立的,有自己的上下文(上下文解释见最下面名词解释部分),线程间的切换是由系统决定的,而协程间也是相互独立的,有自己的上下文,但是它的切换是由当前的协程决定的,而非系统决定的。
4.守护进程
守护进程是指运行在后台的服务端的程序,由于没有控制终端,所以不可以与前台进行交互,它的生成开始与系统的运行,它的结束在系统的关闭。
守护线程指通用的后台服务线程,如垃圾回收。

多进程与多线程
多进程在笔者看来是提升系统执行效率的一种方式,如我们一边听歌,一边打印东西,这是两个不同的进程,由于进程间的同步,似的系统的效率更高,当然,现在的计算机拥有多个cpu,所以可以完成程序进程的并行,即同一时刻运行不同的程序,但是也存在单个处理器的情况,这时涉及到了程序的并发技术,即在一段时间内完成多个任务,据一个例子,一个年级的三个班同时在三个不同的教室上课,那么他们的上课是并行的,但是如果学校只有一间教室,那么三个班要在一天内轮流使用教室,这就是并发,当然了程序的并发的一段时间很短,我们可以参考时间片轮转调度的方法,即每个进程占用cpu的时间很短且固定。这里涉及到了程序的并行与并发,需要注意以下。

多线程在笔者看来是提升系统资源利用率的一种方式,因为一个进程包含多个线程,而线程间公用进程资源,所以共享统一内存,不需要进行内存间特殊数据的传递,所以开销明显会小很多。多线程其实是另一种技术,设计者将一个进程分为多个线程,每个进程中的线程轮流使用cpu,这也实现了多任务的并发。

接下来解决第一段的两个问题即进程间的通信(IPC)和线程间的资源共享互斥问题。
1.进程间的通信机制(IPC)
定义:至少两个进程(或线程)之间传送数据或信号的一些技术和方法。就像前面提到的,进程拥有自己的资源,所以如果一个进程想要访问另外一个进程的数据需要进行进程间的通信。通信可以是在一台计算机上完成也可以在联网的不同计算机上完成。
进程间通信技术包括消息传递,同步,共享内存和远程过程调用,IPC是一种标准的unix通信机制。
使用IPC的好处:
信息共享,加速,模块化以及私有权分离
主要的IPC方法:
1. 管道pipe:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
2. 命名管道FIFO:有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
4. 消息队列MessageQueue:消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
5. 共享内存SharedMemory:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。
6. 信号量Semaphore:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
7. 套接字Socket:Socket(解释见下方名词解释部分)。
8. 信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

2.线程间同步
线程间的同步通常应用信号量和互斥锁。
信号量:是E.W.Dijkstra(了不起的人物)提出的方法,表示可用资源的个数,要么为0,表示没有资源可用需要等待,要么为正数。
信号量通常进行P、V原语操作,P(wait)代表申请信号量一旦成功,信号量个数减1,V(signal)代表释放信号量,当任务完成以后,释放信号量,信号量个数加1。原语指的是不可分割的一系列操作,要么不执行,要么在执行的过程中不可停止。
互斥锁:互斥锁我们可以将它看成信号量的简化版,它只有0,1两种状态即锁和没锁,通常对应有lock和unlock两种状态,lock进行申请,一旦资源是空闲的,则申请成功,并且完成锁定资源,防止其它进程进行访问,当资源使用完后,进行unlock释放资源,撤销锁。

由此我们可以发现,因为信号量可以为0或者正值,而互斥锁只能为0或者1,信号量是完成线程的同步,而互斥锁是完成的线程间的互斥,这是信号量与互斥锁的最主要区别。

艾兹格·W·迪科斯彻(Edsger Wybe Dijkstra)
1 提出“goto有害论”;
2 提出信号量和PV原语;
3 解决了“哲学家聚餐”问题;
4 Dijkstra最短路径算法和银行家算法的创造者;
5 第一个Algol 60编译器的设计者和实现者;
6 THE操作系统的设计者和开发者;

补充:上面提到了时间片轮转的调度算法,那么在这里笔者顺便补充一下操作系统的任务调度的几种算法:

1.FCFS:先来现服务调度算法,即按照进程申请的先后次序进行排序,处理器优先服务最早申请的进程,直到进程结束或者由于某些事件而导致当前进程阻塞。
2.SJF:短作业优先,根据进程的估计运行时间,选取最短运行时间的进程,给其分配处理器,直至进程运行结束或因为某个事件阻塞放弃处理器。
3.高优先级优先:高优先级优先调度算法则是对每个进程给定优先级,根据优先级的大小分配处理器,通常分为抢占式和非抢占式。抢占式即,当一个最高优先级的进程在处理器上运行的时候,又来了一个更高优先级的进程,则中断当前进程,处理器去处理新来的更高优先级的进程。非抢占式则要等到当前进程运行完毕或者因为某件事情阻塞,新来的更高优先级的进程才能占用cpu。
4.高响应比优先:优先级=(等待时间+服务时间)/服务时间 我们会让已经等了更长时间并且占用cpu时间更短的进程占用cpu。
5.时间片轮转:时间片轮转上面已经介绍过,这里不在赘述。
6.多级反馈队列调度:有多个拥有不同优先级的进程队列,如第一个进程队列优先级高,第二个相对地有个低,第三个相对第二个低,以此类推。但是需要注意的是尽管第一个队列优先级高,但是它的被分配的占用处理器的时间片少,这样其它优先级的进程不必担心永远得不到服务。如果第一个队列的进程没有在给定的时间片内完成,则它将会被安排到第二个队列的末尾等待处理器的处理,队列内按照顺序占用处理器。

名词解释:
本地变量:本地变量=局部变量=自动变量(因为局部变量的生存周期是在函数内部,其伴随着函数运行的结束而消亡所以也叫自动变量,函数的运行结束标志是运行到},我们管{}叫做块)。

上下文切换:由于多线程间是轮流占用cpu的,时间短且固定,所以在这段时间内,线程有可能结束不了,这时候cpu需要保存当前线程的状态,以便其下次到来的时候恢复其状态,从任务的保存到加载就是一次上下文的切换。

Socket:Socket 也称为“套接字”。是网络通信中的概念,它分为流式套接字和用户数据报套接字两种,分别对应于网络传输控制层中的TCP和UDP协议。TCP是面向连接的协议,提供稳定的双向通信功能,TCP连接的建立需要经过“三次握手”才能完成,为了提供稳定的数据传输功能,其本身提供了超时重传机制,因此具有很高的稳定性。而UDP是无连接的,提供不稳定的单向通信功能,当然UDP也能实现双向通信功能。在性能上,UDP 具有更高的效率,缺点是不保证数据一定能够正确传输,尤其是在网络阻塞的情况下。 tcp和udp的具体区别见笔者网络安全博客。

POSIX 全称:Portable Operating System Interface of UNIX 可移植性操作系统接口 它是一种标准,定义了操作系统应该为应用程序提供的接口标准,凡支持此标准的操作系统可以完成代码级的软件移植,当然,并不仅限于UNIX。

死锁产生的四个必要条件
1.互斥条件
2.请求和保持条件
3.不抢占条件
4.循环等待条件

哲学家就餐问题:几个哲学界围绕着一个桌子进行就餐,如五个哲学家围绕着一个拥有5支筷子的五个碗的桌子吃饭,哲学家有思考、饥饿、拿起筷子、就餐、放下筷子五个状态。如果五个哲学家同时饥饿,这是他们会同时拿起左手边的筷子,由于右手没有筷子,所以他们陷入了等待状态,称为死锁。
解决这个问题死锁状态有三个通常办法:1.只有同时拥有左右两只筷子才允许进餐,否则放下筷子。2.最多允许四个哲学家同时出现饥饿状态,这样肯定有一位哲学家进餐成功,然后会多出两只筷子义工其他人使用。3.奇数位置的人优先申请左手边的筷子,偶数位置的人优先申请右手边的筷子。

银行家算法:银行家算法主要是避免死锁的方法,可行的情况并不惟一,表内几个进程需求分为最大需求量,已分配资源数,还需要资源数和当前可用资源数,接下来就是对比可用资源数和每个进程还需要的资源数,一旦满足,则将资源分配给该进程,然后释放该进程被分配的资源,于是可用资源就变多了,以此类推。因为在选择满足条件的进程的时候可能有多个进程满足,所以进程的被执行顺序不唯一。

用户评论