1.消息传递
进程交互时必须满足两个基本要求:同步和通信。为实施同步,进程间需要互斥;为了合作,进程间需要交换信息,提供这种功能的一种方法是消息传递。消息传递还有一个优点,即可以在分布式系统、共享内存的多处理器系统和单处理器系统中实现。为什么?因为消息只要指明源和目的就可以了,而信号量是要两个进程修改同一位置的控制数据的。
消息传递的实际功能以一对原语的形式提供:
send(destination, message)
receive(source, message)
关于send和receive操作之后进程的状态变化可以有三种组合:
1) 阻塞send,阻塞receive
2) 无阻塞send,阻塞receive
3) 无阻塞send,无阻塞receive
操作系统通常实现一种或两种组合。对于大多数应用来说无阻塞send,阻塞receive最自然。但是无阻塞send存在一个潜在的危险:错误将会导致进程重复地产生消息。由于对进程没有阻塞的要求,这些消息可能会消耗系统资源。同时,无阻塞send给程序员增加了负担,由于必须确定消息是否收到,因而进程必须使用应答消息,以证实收到了消息。阻塞receive也带来一定的风险,如果消息丢失了(在分布式系统中很可能),或者发送消息的进程在发消息之前失败了,那么接受进程将无限期地被阻塞下去。
2.寻址方式
消息的寻址有两种方式,直接寻址、间接寻址——将消息发送到一个共享数据结构(邮箱)。间接寻址可以实现一(多)对一(多)。
3.代码示例
const int n = /*进程数*/
void P(int i)
{
message msg;
while (true) {
receive (box, msg);
/*临界区*/;
send (box, msg);
/*其他部分*/;
}
}
void main()
{
create mailbox (box);
send (box, null);
parbegin (P(1), P(2), . . ., P(n));
/*用消息传递解决生产者/消费者问题*/
const int
capacity = /*缓冲区容量*/ ;
null = /*空消息*/ ;
int i;
void producer()
{ message pmsg;
while (true) {
receive (mayproduce,pmsg);
pmsg = produce();
send (mayconsume,pmsg);
}
}
void consumer()
{ message cmsg;
while (true) {
receive (mayconsume,cmsg);
consume (cmsg);
send (mayproduce,null);
}
}
void main()
{
create_mailbox (mayproduce);
create_mailbox (mayconsume);
for (int i = 1;i <= capacity;i++) send (mayproduce,null);
parbegin (producer,consumer);
}