第2章-3 进程通信

本文详细介绍了进程通信的三种主要机制:共享存储区、消息传递(包括直接和间接通信)以及线程的基本概念。通过具体示例展示了Linux中如何使用共享内存和消息队列进行进程间通信,并探讨了线程与进程的区别,强调了线程作为执行单元的轻量级特性及其在并发执行中的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2.6 进程通信IPC

进程通信:进程之间的信息交换。
IPC ( Inter-Process Communication)
进程是分配系统资源的单位,各进程拥有的内存地址空间相互独立。
在这里插入图片描述
为了保证安全,一个进程不能直接访问另一个进程的地址空间。
但由此也造成了进程之间无法直接交换数据,需要借助进程通信机制来实现。
根据交换信息量的多少和效率的高低,进程通信分为低级通信和高级通信。

  1. 低级通信
    传送信息量小,效率低,每次通信传递的信息量固定,若传递较多信息则需要进行多次通信。如:信号量机制。
    编程复杂:用户直接实现通信的细节,容易出错,对用户不透明。
  2. 高级通信
    用户直接利用OS提供的通信命令传输大量数据,减轻程序编制的
    复杂度。通信控制细节由OS完成。
    高级通信特点:使用方便,高效地传送大量数据。

在这里插入图片描述

2.6.1 共享存储区

  1. 在内存中划出一块区域作为共享数据区,称为共享内存分区,通信进程双方将共享区附加到自己的进程空间中。
  2. 通信时,发送进程将信息写入该共享内存区中,接收进程从中读取信息。
    在这里插入图片描述
    注意:共享存储区机制只为进程提供了用于实现通信的共享存储区。未提供对该区进行互斥访问及进程同步的措施。因此,程序自己设置同步和互斥措施,才能保证实现正确的通信。

例子::Linux中的shared memory实现
在这里插入图片描述
共享存储区完成两个进程的通信——生产者:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define KEY 75
#define SIZE 1024
main( )
{int shmid, 
*p, i;
char *shmaddr;
shmid=shmget(KEY, SIZE,
0777|IPC_CREAT);
shmaddr=shmat(shmid,0, 0);
p=(int *) shmaddr;
for(i=0; i<10; i++) {
*p= i*i*i;
printf(%d\n”,*p);
p++; 
sleep(1);
}
sleep(5); 
shmdt(shmaddr); }

IPC_CREAT: 新建一个共享内存;如果存在这样的共享内存,返回此共享内存的标识符.shmat: 把共享内存连接到当前进程的地址空间。

共享存储区完成两个进程的通信——消费者:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define KEY 75
#define SIZE 1024
main( )
{int mid;*q,*t,i;
char * maddr;
mid=shmget(KEY, SIZE, 0777);
maddr=shmat(mid,0,0);
q=(int *) maddr;
sleep(12);
for(i=0;i<10;i++)
printf(%d”, *q++);
shmdt(maddr);
shmctl(shmid, IPC_RMID, 0);
}

2.6.2 消息传递机制

信息交换的单位称为消息或报文。有两种方式:

1.直接通信方式
2.间接通信方式
在这里插入图片描述

  1. 直接消息传递机制
    在这里插入图片描述
    解决生产者和消费者问题:
    在这里插入图片描述

  2. 间接通信方式
    在这里插入图片描述
    在这里插入图片描述
    消息的发送和接收:
    send(mailbox,信件):若信箱未满,则把一消息发送到信箱,同时唤醒信件等待者进程,否则发送者阻塞.
    receive(mailbox,信件):若信箱不空,则从信箱接收消息,同时唤醒等待发送者进程;否则接受者阻塞。

2.6.3 直接消息传递系统实例

  1. 消息缓冲队列通信机制中的数据结构
    (1) 消息缓冲区
    消息缓冲队列通信方式中,主要的数据结构是消息缓冲区。
typedef struct message_buffer {
int sender; //发送者进程标识符
int size; //消息长度
char *text; //消息正文
struct message_buffer *next;
//指向下个消息缓冲区的指针
}

程序组织消息,使用发送原语发送。

(2) PCB中有关通信的数据项
PCB中增加对消息队列进行操作和实现同步的信号量;
PCB中增加的数据项描述如下:

type processcontrol_block {
struct message_buffer *mq; 消息队列队首指针
semaphore mutex; 消息队列互斥信号量
semaphore sm; 消息队列资源信号量
}
  1. 发送原语
    根据发送消息的长度,申请一缓冲区i,把发送区a中的信息复制到缓冲区i中。
    在这里插入图片描述
procedure send(receiver, a) { //a为发送区首址
getbuf(a.size, i); // 根据a.size申请缓冲区
i.sender=a.sender; //将发送区a中信息复制到消息缓冲区中;
i.size =a.size; i.text =a.text; i.next=0;
getid(PCBset, receiver.j); //获得接收进程内部标识符;
wait(j.mutex);
insert(j.mq, i); //将消息缓冲区插入消息队列,互斥访问;
signal(j.mutex);
signal(j.sm); }
  1. 接收原语:从自己的消息缓冲队列mq中,摘下第一个消息缓
    冲区, 并复制到接收区内。
    接收原语描述如下:
procedure receive(b) { j =internal name; // j为接收进程内部的标识符;
wait(j.sm); //是否有消息
wait(j.mutex);
remove(j.mq, i); // 将消息队列中第一个消息移出,互斥访问;
signal(j.mutex); b.sender=i.sender; //将消息缓冲区i中的信息复制到接收区b; b.size =i.size; b.text =i.text;
releasebuf(i);
}

例:Linux消息传递

struct msgbuf{
long mtype; /* message type*/
char mtext[512]; /* message data */
};

int msgget(key_t key, int msgflg);
功能:创建一个消息队列,或取得一个已经存在的消息队列。
返回值:成功返回消息队列的标示符(ID),失败为-1;

int msgsnd(int msgid, struct msgbuf *msgp , int msgsz, int msgflg);
功能:往队列中发送一个消息。
返回值:成功返回0,失败返回-1;

msgsz, :消息的字节大小,不包含消息类型的长度(4个字节)
msgflg :设置IPC_NOWAIT, 如果消息队列已经满,控制将返回到本进程;如果没有指明,调用进程会被挂起,直到消息可以写到消息队列中。

int msgrcv(int msgid, struct msgbuf *msgp, int msgsz ,
long mtype, int msgflg );
功能:从消息队列中读取消息。
返回值:成功返回0,失败返回-1;

参数:
msgp: 存储消息的地址
msgsz:消息的长度不包含mtype的长度
msgsz=sizeof(struct msgbuf)-sizeof(long);
mtype:从消息队列中读取的消息的类型。
如果此值为0,则会读取时间最长的一条消息。
msgflg:为0代表该进程将一直阻塞,直到有消息可读停止。
为IPC_NOWAIT,如果没有消息可读时,则立刻返回-1

服务器进程:

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define MSGKEY 75
struct msgform
{ long mtype;
 char mtext[256];
 }msg;
 int msgqid, i;
 main()
{int msgid,p,i;
struct msgbuf msg;
msgid=msgget(KEY, 
0777|IPC_CREAT);
while1{
msgrcv(msgid, &msg, 256, 1, 0);
p=(int*)msg.mtext;
msg.mtype=*p;
msg.mtext=“OK”;
msgsnd(msgid,&msg,2,0);
}..
}

客户端进程:

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define MSGKEY 75
struct msgform
{ long mtype;
char mtext[256];
}msg;
int msgqid, i;
main()
{int mid;*q,*t;
struct msgbuf m;
mid=msgget(KEY, 0777);
t=getpid();
m.mtype=1;
q=(int*)m.mtext;
*q=t;
msgsnd(mid,&m,sizeof(int),0);..msgrcv(mid,&m,256,t,0);
printf(%s”,m.mtext);.
}

2.7 线程的基本概念

进程并发执行时OS必须的操作:

创建进程: 系统分配资源,如:PCB,内存空间,I/O设备
进程切换: 对进程进行切换时,保留当前进程CPU环境,设置新选中进程的CPU环境;
撤销进程:回收其占有的资源,撤销PCB

进程的两个基本属性:

(1)进程是一个可拥有资源的独立单位.如:内存、打开的文件,信号量等;
(2)进程是一个可独立调度和分派的基本单位。每个进程有唯一的PCB,系统根据PCB对其进行调度,将断点信息保存在其PCB中。

2.7.1 线程的引入

引入线程,线程是CPU调度和执行的最小单元,改善处理机的性能。

(1)进程内的一个执行单元。
(2)进程内的一个可独立调度的实体。
(3)线程是进程中一个相对独立的控制流序列。

线程属性

(1)线程属于轻型实体,基本不拥有系统资源,只拥有为保证其运
行而必不可少的资源。
(2)线程是独立调度和分派的基本单位,能够独立运行的基本单位。 (3)同一个进程中的所有线程,共享该进程所拥有的全部资源。

进程——资源分配的最小单位,线程——程序执行的最小单位

2.7.2 线程与进程的比较

在这里插入图片描述
(1)调度的基本单位。进程除了是调度和分派的基本单位以外,还是资源分配的基本单位。而线程只是调度和分派的基本单位。
(2)并发性。在引入线程的系统中,同一个进程中的多个线程可以并发执行,且属于不同进程中的多个线程也可以并发执行,线程并发执行的程度高于传统进程并发执行的程度。(线程应用:一个实现天气预报的程序可以将处理北京、上海、深圳地区天气数据的过程并行地展开。)
(3)拥有资源。进程是系统资源分配的基本单位。线程基本不拥有资源,可以使用它所隶属进程的资源,如程序段、数据段、打开的文件及I/O设备等。
(4)数据传递。不同进程数据传递通过进程通信方式进行;一个进程的数据空间被该进程的所有线程所共享,一个线程的数据可以直接被属于同一个进程的其他线程所使用。
(5)时空开销。创建、切换和撤销一个线程所花费的时空开销小于创建和撤销一个传统进程所花费的时空开销。

例题及参考答案

为什么引入进程,进程和程序的区别?

答:想提高程序并发执行的程度,所以引入进程。进程和程序的区别和联系:
1、程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。而进程是程序在处理机上的一次执行过程,它是一个动态的概念。
2、程序可以作为一种软件资料长期存在,而进程是有一定生命期的。程序是永久的,进程是暂时的。
3、进程更能真实地描述并发,而程序不能;
4、进程是由进程控制块、程序段、数据段三部分组成;
5、进程具有创建其他进程的功能,而程序没有;

  1. 一个进程释放了一台打印机,它可能会改变(C)的状态。
    A 自身进程
    B 输入/输出进程
    C 另一个等待打印机的进程
    D 所有等待打印机的进程

  2. 在进程状态转换时,下列( D )转换是不可能发生的。
    A 就绪态→运行态
    B 运行态→就绪态
    C 运行态→阻塞态
    D 阻塞态→运行态

  3. 在一段时间内,只允许一个进程访问的资源称为(C )。
    A 共享资源
    B 临界区
    C 临界资源
    D 共享区

  4. 进程之间交换数据不能通过(C)途径进行。
    A 共享文件
    B 消息传递
    C 访问进程地址空间
    D 访问共享存储区

  5. 操作系统是根据(B)来对并发执行的进程进行控制和管理的。
    A 进程的基本状态
    B 进程控制块
    C 多道程序设计
    D 进程的优先权

  6. 进程创建时,不需要做的是(D)。
    A 填写一个该进程的进程表项
    B 分配该进程适当的内存
    C 将该进程插入就绪队列
    D 为该进程分配CPU

  7. 与时间有关的错误是指( C )
    A 与进程执行的时间长短有关
    B 与CPU的速度有关
    C 与进程被打断的时间有关
    D 与超时有关

  8. 从执行状态挂起的进程解除挂起时进入(A)状态
    A 就绪
    B 执行
    C 阻塞
    D 挂起

  9. 操作系统中有一组常称为特殊系统调用,它不能被系统中断,在操作系统中称为( B)。
    A 初始化程序
    B 原语
    C 子程序
    D 控制模块

  10. 当(B )时,进程从执行状态转变为就绪状态。
    A 进程被调度程序选中
    B 时间片到
    C 等待某一事件
    D 等待的事件发生

  11. 同一个程序经过多次创建,运行在不同的数据集上,形成了(A)的进程。
    A 不同
    B 相同
    C 同步
    D 互斥

  12. 下列各项步骤中,哪一个不是创建进程所必须的步骤( B)。
    A 建立一个进程控制块PCB
    B 由CPU调度程序为进程调度CPU
    C 为进程分配内存等必要的资源
    D 将PCB链入进程就绪队列

  13. 进程间的基本关系为( B)。
    A 相互独立与相互制约
    B 同步与互斥
    C 并行执行与资源共享
    D 信息传递与信息缓冲

  14. PV操作是( A )。
    A 两条低级进程通信原语
    B 两组不同的机器指令
    C 两条系统调用命令
    D 两条高级进程通信原语

  15. 在操作系统中,对信号量S的P原语操作定义中,使进程进入相应等待队列等待的条件是(C)。
    A S>0
    B S=0
    C S<0
    D S<>0

  16. 在进程通信中,使用信箱方式交换信息的是( B )
    A 低级通信
    B 高级通信 (答案)
    C 共享存储器通信
    D 管道通信

  17. 关于进程,下列叙述不正确的是( D )
    A 进程包含了数据和运行其上的程序
    B 同一个程序运行在不同的数据集合上时,构成了不同的进程
    C 一个被创建了的进程,在它消亡之前,总是处于3种基本状态之一
    D 干个进程在单CPU系统中必须依次执行,即一个进程完成后,另一个进程才能开始工作

  18. 进程和程序的本质区别是( D)。
    A 存储在内存和外存
    B 顺序和非顺序执行机器指令
    C 分时使用和独占使用计算机资源
    D 动态和静态特征

  19. 一个进程是(C )
    A 由处理机执行的一个程序
    B 一个独立的程序+数据集
    C PCB结构与程序和数据的组合
    D 一个独立的程序

  20. 进程控制块是描述进程状态和特性的数据结构,一个进程(D )。
    A 可以有多个进程控制块
    B 可以和其他进程共用一个进程控制块
    C 可以没有进程控制块
    D 只能有唯一的进程控制块 (答案)

  21. 临界区是指( D )。
    A 并发进程中用于实现进程互斥的程序段
    B 并发程序中用于实现进程同步的程序段
    C 并发程序中用于实现进程通信的程序段
    D 并发程序中与共享变量有关的程序段

  22. 如果某一进程获得除CPU外的所有所需运行资源,经调度,分配给它CPU,该进程将进入(B )。
    A 就绪状态
    B 运行状态
    C 等待状态
    D 活动状态

  23. 两个进程合作完成一个任务,在并发执行中,一个进程要等待另一个进程的结果,或者建立某个条件后再向前继续执行,这种关系属于进程间的( A)关系。
    A 同步
    B 异步
    C 互斥
    D 流水线

  24. 下列有可能导致一进程从运行变为就绪的事件是( D)
    A 一次I/O操作结束
    B 运行进程需作I/O操作
    C 运行进程结束
    D 出现了比现运行进程优先权更高的进程

  25. 各进程向前推进的速度是不可预知的,体现出“走走停停”的特征,称为进程的( C )
    A 动态性
    B 并发性
    C 异步性
    D 调度性

二、判断题

  1. 临界资源是指每次仅允许一个进程访问的资源。(对)
  2. 并发是并行的不同表述,其原理相同。(错)
  3. 利用信号量的PV操作可以交换大量的信息。(错)
  4. V操作是对信号量执行加1操作,意味着释放一个单位资源,加1后如果信号量的值等于零,则从等待队列中唤醒一个进程,现进程变为等待状态,否则现进程继续进行。(错,阻塞队列中有申请资源S的阻塞进程,从S.L所指的阻塞队列中移出队首进程i,置进程i的状态为“就绪”,将进程i插入到就绪队列中)
  5. 信号量机制是一种有效的实现进程同步与互斥的工具。信号量只能由P-V操作来改变;(对)
  6. P操作和V操作都是原语操作。(对)
  7. 进程之间同步,主要源于进程之间的资源竞争,是指对多个相关进程在执行次序上的协调;(错,应该是进程之间的互斥)
  8. 进程的相对运行速度不能由自己来控制。(对)
  9. 如果系统中有N个进程,则在就绪队列中进程的个数最多为N.(错,为N-1)
  10. 并发进程在访问共享资源时,不可能出现与时间有关的错误。(错,与时间有关的错误是指与进程被打断的时间有关)

三、问答题

  1. 试利用记录型信号量写出一个不会出现死锁的哲学家进餐问题的算法.

答:只允许4个哲学家同时进餐,以保证至少有一个哲学家可以进餐,最终才能由他释放出其所用过的两支筷子,从而使更多的哲学家可以进餐。为此,需设置一个信号量Sm来限制同时进餐的哲学家数目,使它不超过4,故Sm的初值也应设成4。

  1. 在一个单CPU的多道程序设计系统中,若在某一时刻有N个进程同时存在,那么处于运行态、等待态和就绪态进程的最小和最大值分别可能是多少?

答:处于运行态的进程最小可能是0个,即所有进程都被阻塞的情况;最大是1个,因为单CPU同时只能运行一个进程。
处于等待态的进程最小可能是0个;最大可能有N 个,即所有进程都被阻塞。
处于就绪态的进程最小可能是0个;最大是N-1个,因为不可能全部进程都在就绪状态而CPU不执行其中的任何一个。

  1. 进程之间存在着哪几种制约关系?各是什么原因引起的?下列活动分别属于哪种制约关系?(1)若干同学去图书馆借书;(2)两队举行篮球比赛;(3)流水线生产的各道工序;(4)商品生产和社会消费。

答:进程之间存在着直接制约和间接制约两种制约关系,其中直接制约(同步)是由于进程间的相互合作而引起的,而间接制约(互斥)则是由于进程间共享临界资源而引起的。(1) 若干同学去图书馆借书是间接制约,其中书是临界资源。(2) 两队举行篮球比赛是间接制约,其中篮球是临界资源。(3) 流水线生产的各道工序是直接制约,各道工序间需要相互合作,每道工序的开始都依赖于前一道工序的完成。(4) 商品生产和社会消费是直接制约,两者也需要相互合作:商品生产出来后才可以被消费;商品被消费后才需要再生产。

  1. 如何理解进程的顺序性与并发性?

答:1、顺序性
顺序性包括两层含义:(1)内部顺序性,对于一个进程来说,它的所有指令是按序执行的;(2)外部顺序性,对于多个进程来说,所有进程是依次执行的。
例如,假如有P1和P2两个进程,其活动分别为:
P1活动:A1 A2 A3 A4
P2活动:B1 B2 B3 B4
顺序执行时,有如下两种情形:
情形1:A1 A2 A3 A4 B1 B2 B3 B4
情形2:B1 B2 B3 B4 A1 A2 A3 A4
2、并发性
并发性包括如下两层含义:(1)内部顺序性,对于一个进程来说,它的所有指令是按序执行的;(2)外部并发性,对于多个进程来说,所有进程是交叉执行的。
例如,对于上面P1和P2两个进程来说,并发执行有许多情形,如:
情形1:A1 B1 B2 A2 A3 B3 A4 B4
情形2:B1 B2 A1 A2 A3 B3 B4 A4
并发进程在其执行过程中,出现哪种交叉情形是不可预知的,这就是并发进程的不确定性,操作系统应当保证:无论出现何种交叉情形,每个进程运行的结果都应当是唯一的,正确的。

  1. 什么是线程?它与进程有什么关系?

答:线程是进程中执行运算的最小单位,即处理机调度的基本单位。它与进程的关系是:一个线程只能属于一个进程,而一个进程可以有多个线程;资源分配给进程,同一进程的所有线程共享该进程的所有资源;处理机分给线程,即真正在处理机上运行的是线程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值