程序、进程和线程
进程是操作系统最重要的核心概念之一,对进程的不同实现方式造成了目前操作系统的一种分类方法,例如 DOS 系统为单进程的操作系统。本篇博客中将介绍 Linux 中进程的概念和相关的操作函数,并对线程的程序设计方法进行比较多的介绍,主要包括如下内容:
█ 进程、线程和程序的概念和它们之间的区别;
█ 进程的产生方式,fork()、system()、exec() 函数等;
█ Linux 进程间的通信和同步方式,包括管道 pipe、命名管道 fifo、信号量 sem、共享缓冲区 shm、消息队列 msg,以及信号 signal。对其原理和编程函数进行详细的讲解,并例举丰富的代码例子;
█ 对 Linux 下的线程编程方式进行详细介绍,并介绍互斥、条件变量、线程信号等编程实现方法。
程序、进程和线程的概念
在计算机上运行的程序是一组指令及指令参数的组合,指令按照既定的逻辑控制计算机运行。进程则是运行着的程序,是操作系统执行的基本单位。线程则是为了节省资源而可以在同一个进程中共享资源的一个执行单位。
一、程序和进程的差别
进程的出现最初是在 UNIX 下,用于表示多用户、多任务的操作系统环境下,应用程序在内存环境中基本执行单元的概念。
进程是 UNIX 操作系统环境中的基本概念,是系统资源分配的最小单位。
UNIX 操作系统下的用户管理和资源分配等工作几乎都是操作系统通过对应用程序进程的控制实现的。
C、C++、Java 等语言编写的源程序经相应的编译器编译成可执行文件后,提交给计算机处理器运行。应用程序的运行状态称为进程。
进程从用户角度来看是应用程序的一个执行过程。
从操作系统核心角度来看,进程代表的是操作系统分配的内存、CPU 时间片等资源的基本单位,是为正在运行的程序提供的运行环境。
进程与应用程序的区别在于应用程序作为一个静态文件存储在计算机系统的硬盘等存储空间中,而进程则是处于动态条件下由操作系统维护的系统资源管理实体。
进程概念和程序概念最大的不同之处在于:
█ 进程是动态的,而程序是静态的;
█ 进程有一定的生命期,而程序是指令的集合,本身无 “运动” 的含义。没有建立进程的程序不能作为 1 个独立单位得到操作系统的认可;
█ 一个进程只能对应一个程序,一个程序可以对应多个进程。进程和程序的关系就像戏剧和剧本之间的关系。
二、Linux环境下的进程
Linux 的进程操作方式主要有产生进程、终止进程,并且进程之间存在数据和控制的交互,即进程间通信和同步。
1. 进程的产生过程
进程的产生有多种方式,其基本过程是一致的。
(1) 首先复制其父进程的环境配罝。
(2) 在内核中建立进程结构。
(3) 将结构插入到进程列表,便于维护。
(4) 分配资源给此进程。
(5) 复制父进程的内存映射信息。
(6) 管理文件描述符和链接点。
(7) 通知父进程。
2. 进程的终止方式
有 5 种方式使进程终止。
█ 从 main 返回。
█ 调用 exit。
█ 调用 _exit。
█ 调用 abort。
█ 由一个信号终止。
进程在终止的时候,系统会释放进程所拥有的资源,例如内存、文件符和内核结构等。
3. 进程之间的通信
进程之间的通信有多种方式,其中管道、并享内存和消息队列是最常用的方式。
█ 管道是 UNIX 族中进程通信的最古老的方式,它利用内核在两个进程之间建立通道,它的特点是与文件的操作类似,仅仅在管道的一端只读,另一端只写。利用读写的方式在进程之间传递数据。
█ 共享内存是将内存中的一段地址,在多个进程之间共享。多个进程利用获得的共享内存的地址来直接对内存进行操作。
█ 消息队列则是在内核中建立一个链表,发送方按照一定的标识将数据发送到内核中,内核将其放入量表后,等待接收方的请求。接收方发送请求后,内核按照消息的标识,从内核中将消息从链表中摘下,传递给接收方。消息队列是一种完全的异步操作方式。
4. 进程之间的同步
多个进程之间需要协作完成任务时,经常发生任务之间的依赖现象,从而出现了进程的同步问题。Linux 下进程的同步方式主要有消息队列、信号量等。
信号量是一个共享的表示数量的值。用于多个进程之间操作或者共享资源的保护,它是进程之间同步的最主要方式。
三、进程和线程
线程和进程是另一对有意义的概念,主要区别和联系如下。
█ 进程是操作系统进行资源分配的基本单位,进程拥有完整的虚拟空间。进行系统资源分配的时候,除了 CPU 资源之外,不会给线程分配独立的资源,线程所需要的资源需要共享。
█ 线程是进程的一部分,如果没有进行显式地线程分配,可以认为进程是单线程的;如果进程中建立了线程,则可以认为系统是多线程的。
█ 多线程和多进程是两种不同的概念,虽然二者都是并行完成功能。但是,多个线程之间像内存、变量等资源可以通过简单的办法共享,多进程则不同,进程间的共享方式有限。
█ 进程有进程控制表 PCB,系统通过 PCB 对进程进行调度;线程有线程控制表 TCB。但是,TCB 所表示的状态比 PCB 要少得多。