进程间同步的几种方法

什么是临界区?

每个进程中访问临界资源的那段程序称为临界区(临界资源是一次仅允许一个进程使用的共享资源)。每次只准许一个进程进入临界区,进入后不允许其他进程进入。

进程间同步

把异步环境下的一组并发进程因直接制约而互相发送消息而进行互相合作、互相等待,使得各进程按一定的速度执行的过程称为进程间的同步。

实现进程间同步主要有如下方法:

  • 信号量

  • 用P、V原语

  • 生产者-消费者模型


1 信号量

一种最为简单和直观的方法是直接制约的进程互相给对方进程发送执行条件已经具备的信号。这样,被制约进程即可省去对执行条件的测试,只要收到了制约进程发来的信号便开始执行,而在未收到制约进程发来的信号时便进入等待状态。

2 用P、V原语

P操作:

p(s)是一个原语操作,p操作执行 s– ,若s为负数,调用p(s)的进程被阻塞,放到等待队列q中。

V操作

v(s)刚好与p(s)操作相反,v操作执行 s++ ,若s为大于0,继续执行;s <=0,从信号灯等待队列移出一个进程,解除等待状态,返回本程序继续执行。

使用P、V原语操作实现进程间的同步,分为3步:

  1. 首先为各并发进程设置私用信号量
  2. 然后为私用信号量赋初值
  3. 最后利用P、V原语和私用信号量规定各进程的执行顺序

3 生产者-消费者模型

并发进程同步和互斥问题,一般都可以抽象为生产者-消费者问题。

4 参考资料

张尧学著《计算机操作系统教程》第4版

### Linux 进程间通信方法概述 在Linux环境中,进程间通信(IPC)对于实现多任务处理至关重要。通过这些机制可以完成数据传输、共享资源、通知事件以及控制进程等功能[^1]。 #### 管道 (Pipe) 和有名管道 (FIFO) 这两种方式主要用于具有亲缘关系的进程之间交换信息。普通管道仅限于父子进程或者兄弟进程间的单向通讯;而命名管道则可以通过文件系统访问,支持任意两个进程之间的双向交流[^2]。 ```bash mkfifo mypipe echo "hello" > mypipe & cat mypipe ``` #### 信号 (Signal) 这是一种异步的通知机制,用来告知目标进程发生了特定类型的事件。尽管其功能强大,但由于缺乏传递复杂结构化数据的能力,在实际应用中通常与其他形式配合使用。 #### 消息队列 分为POSIX标准的消息队列和System V风格的消息队列两种类型。消息队列为应用程序提供了可靠的存储转发服务,即使接收方暂时不可用也能保证消息最终送达。 ```c #include <mqueue.h> mqd_t mq; struct mq_attr attr; attr.mq_flags = O_RDWR | O_CREAT; attr.mq_maxmsg = 10; attr.mq_msgsize = sizeof(int); mq = mq_open("/my_queue", attr); if(mq != (mqd_t)-1){ int msg = 42; mq_send(mq, (char*)&msg, sizeof(msg), 0); } ``` #### 信号量 / 信号灯 这不仅是一种同步工具,还可以作为计数器来管理公共资源的数量限制。当多个进程试图同时访问有限数量的相同资源时,信号量可以帮助协调它们的行为,防止竞争条件的发生。 #### 共享内存 这是效率最高的IPC方式之一,允许多个进程映射相同的物理页面到各自的地址空间内直接读写。然而由于缺少天然的安全保障措施,因此往往还需要额外引入诸如互斥锁之类的保护手段以确保一致性。 ```c #include <sys/ipc.h> #include <sys/shm.h> key_t key = ftok("shmfile",65); int shmid = shmget(key,1024,0666|IPC_CREAT); char *str=(char*)shmat(shmid,(void*)0,0); strcpy(str,"Hello World"); printf("%s\n", str); ``` #### 套接字 (Socket) 除了本地主机上的进程外,套接字还适用于网络上跨计算机系统的远程过程调用场景。它遵循TCP/IP协议栈的规定,具备良好的可移植性和兼容性特点。 ```python import socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(('localhost', 8080)) server_socket.listen(5) client_socket, addr = server_socket.accept() data = client_socket.recv(1024).decode('utf-8') print(f"Received data from {addr}: {data}") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值