python中的进程间通信

进程间数据是否共享

在Python中,进程之间默认是不共享内存的。每个进程都有自己独立的内存空间,这意味着在一个进程中对数据的修改不会影响到另一个进程中的同名数据。然而,Python提供了几种方式来实现进程间的数据共享:

  1. 使用 multiprocessing 模块: Python 的 multiprocessing 模块提供了多种方式来实现进程间通信(IPC),其中包括:

    • Value 和 Array: 可以用于存储数据并可以被多个进程共享。
    • Manager: 通过使用 manager 对象,可以创建一个运行在服务器进程中的管理器对象,该对象支持将列表、字典等放在多个进程之间共享。
  2. 使用文件或数据库: 进程可以通过读写文件或操作数据库来交换信息。这种方法相对简单但可能受到I/O性能限制。

  3. 使用消息传递机制:如队列(Queue)和管道(Pipe),这些也是 multiprocessing 提供的功能。它们允许将消息从一个进程传递到另一个,虽然严格意义上不是共享内存,但它们是进行数据交换和任务协调非常有效的手段。

下面是一个简单示例代码说明,在不使用Value的情况下

from multiprocessing import Process, Lock, current_process
import timedef process_with_shared_resource(shared_resource, lock):name = current_process().namelock.acquire()try:print(f"{name} 获取当前共享变量: {shared_resource}")shared_resource += 1time.sleep(0.1)print(f"{name} 更新后的共享变量: {shared_resource}")finally:lock.release()if __name__ == "__main__":# 创建一个共享的资源和锁shared_resource = 0lock = Lock()# 创建多个进程processes = []for _ in range(5):p = Process(target=process_with_shared_resource, args=(shared_resource, lock))processes.append(p)p.start()# 等待所有进程完成for p in processes:p.join()print(f"最终变量值: {shared_resource}")

输出:

Process-3 获取当前共享变量: 0
Process-3 更新后的共享变量: 1
Process-1 获取当前共享变量: 0
Process-1 更新后的共享变量: 1
Process-2 获取当前共享变量: 0
Process-2 更新后的共享变量: 1
Process-4 获取当前共享变量: 0
Process-4 更新后的共享变量: 1
Process-5 获取当前共享变量: 0
Process-5 更新后的共享变量: 1
最终变量值: 0

看到,每个进程都有自己的变量shared_resource,并且初始化值都为0。

优化使用Value后:

from multiprocessing import Process, Lock, current_process, Value
import timedef process_with_shared_resource(shared_resource, lock):name = current_process().namelock.acquire()try:print(f"{name} 获取当前共享变量: {shared_resource.value}")shared_resource.value += 1time.sleep(0.1)print(f"{name} 更新后的共享变量: {shared_resource.value}")finally:lock.release()if __name__ == "__main__":# 创建一个共享的资源和锁shared_resource = Value('i', 0)lock = Lock()# 创建多个进程processes = []for _ in range(5):p = Process(target=process_with_shared_resource, args=(shared_resource, lock))processes.append(p)p.start()# 等待所有进程完成for p in processes:p.join()print(f"最终变量值: {shared_resource.value}")

输出:

Process-1 获取当前共享变量: 0
Process-1 更新后的共享变量: 1
Process-4 获取当前共享变量: 1
Process-4 更新后的共享变量: 2
Process-5 获取当前共享变量: 2
Process-5 更新后的共享变量: 3
Process-2 获取当前共享变量: 3
Process-2 更新后的共享变量: 4
Process-3 获取当前共享变量: 4
Process-3 更新后的共享变量: 5
最终变量值: 5

结果正确了

进程间通信

在前面的学习中我们提到了一个概念,就是主进程的代码执行结束以后,主进程并没有结束的,因为主进程需要等待所有子进程运行代码结束以后,主进程通过系统调用回收子进程的资源,紧接着主进程才进行系统调用回收当前进程的资源。

那么,主进程怎么在数据隔离的情况下知道每一个子进程是什么时候结束的呢?

注意:子进程是完全有可能存在input,recv这样的阻塞代码情况的。实际上,父进程不可能预判到每个子进程什么时候结束的,但是可以让子进程在结束的时候发出一个信号告诉父进程,它结束了。父进程接受到该子进程的结束信号就可以通过系统调用回收子进程的资源了。而这个发出信号与接收信号的过程,就是进程间的通信(IPC)了。

进程间通信(Inter-Process Communication,IPC)是操作系统中允许不同进程之间交换信息的一种机制。在多任务操作系统中,IPC对于实现不同程序组件之间的协作至关重要。由于每个进程都有自己独立的内存空间,所以他们不能直接共享内存中的数据。Python提供了多种机制来实现进程间的通信,主要通过 multiprocessing 模块来完成。

1. 管道(Pipes)

管道是一种最基本的进程间通信方式。在Python中,multiprocessing 模块的 Pipe() 函数可以创建一对连接对象,这两个对象可以在不同进程间通过发送和接收消息来通信。管道可以是单向的(半双工)或双向的(全双工)。

  1. 创建管道:调用multiprocessing.Pipe()将创建一对可以用于进程间通信的文件描述符。

  2. 读写通信:一个进程使用一个文件描述符的一端来发送数据,另一个进程使用另一个文件描述符的另一端来接收数据。

  3. 半双工通信:数据只能在一个方向上流动,这意味着发送方和接收方不能同时发送数据,但可以交替进行。

  4. 关闭管道:通信完成后,应该关闭管道以释放系统资源。

from multiprocessing import Process, Pipe, current_processdef child(conn):str_send = "Hello ~"print(f'{current_process().name} 发送消息:{str_send}')conn.send(str_send)conn.send(str_send)conn.close()if __name__ == '__main__':parent_conn, child_conn = Pipe()p = Process(target=child, args=(child_conn,))p.start()# recv会阻塞调用,直到收到消息print(f"{current_process().name} 接受到消息:{parent_conn.recv()}")print(f"{current_process().name} 接受到消息:{parent_conn.recv()}")# print(f"{current_process().name} 接受到消息:{parent_conn.recv()}") # 阻塞接受消息parent_conn.close()  # 关闭父进程端的管道p.join()  # 等待子进程结束
  • 我们定义了一个child函数,它将通过管道发送一条消息。
  • 在主进程中,我们创建了一个管道,并将管道的两个端点分别赋值给parent_connchild_conn
  • 我们创建了一个子进程,并将child_conn传递给它。
  • 子进程开始运行,并调用child函数,通过管道发送了一条消息。
  • 主进程使用parent_conn.recv()来接收消息,然后打印这条消息。
  • 最后,我们关闭了管道,并等待子进程结束。

注意,multiprocessing.Pipe()主要用于进程间的通信,而不是线程间的通信。

2. 队列(Queues)

队列是用于多个生产者(发送者)和消费者(接收者)的典型场景。它是线程和进程安全的。通过使用 multiprocessing.Queue,可以在进程间安全地交换消息或其他数据。

from multiprocessing import Process, Queue, current_processdef worker(queue):while True:args = queue.get()  # 阻塞调用,直到队列中有数据# 这里可以处理接收到的参数print(f"{current_process().name} 接受到消息到: {args}")if args is None:  # 接收到退出信号breakif __name__ == '__main__':# 创建一个队列q = Queue()# 启动一个工作进程p = Process(target=worker, args=(q,))p.start()# 将数据放入队列for i in range(10):print(f"{current_process().name} 发送消息: {i}")q.put(i)q.put(None)# 等待队列中的所有任务被处理完成p.join()print("结束")

3. 共享内存

multiprocessing 模块还支持通过共享内存来进行进程间通信,主要通过 ValueArray。这允许创建一个可以在多个进程间共享的变量。

最开始的代码例子便使用的是Value模块

4. 管理器(Managers)

multiprocessing 提供了一个 Manager() 方法,用于创建一个管理器对象,该对象支持将Python对象放在服务器进程中,以便不同进程可以通过代理的方式访问。

from multiprocessing import Process, Manager, current_processdef f(d, l):d[1] = '1'd['2'] = 2d[0.25] = Nonel.reverse()if __name__ == '__main__':with Manager() as manager:d = manager.dict()l = manager.list(range(10))print(f"{current_process().name} dict: {d}")print(f"{current_process().name} list: {l}")p = Process(target=f, args=(d, l))p.start()p.join()print(f"{current_process().name} dict: {d}")print(f"{current_process().name} list: {l}")# 子进程已经修改了变量

输出:

MainProcess dict: {}
MainProcess list: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
MainProcess dict: {1: '1', '2': 2, 0.25: None}
MainProcess list: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

进程间的数据隔离

进程间的数据隔离是操作系统设计中的一个核心概念,它确保了不同进程的内存空间和数据是相互独立的,从而防止了进程间的非授权数据访问和潜在的数据冲突。以下是实现进程间数据隔离的一些关键机制:

  1. 独立的地址空间

    • 每个进程都有自己独立的虚拟地址空间,这意味着一个进程的代码和数据不能直接被另一个进程访问。
  2. 内存保护

    • 操作系统通过内存保护机制防止进程访问不属于它的内存区域。如果一个进程尝试访问另一个进程的内存,操作系统将触发一个保护错误(通常是段错误)。
  3. 分页机制

    • 操作系统使用分页机制来管理内存,每个进程的页表是独立的,映射到物理内存的地址也是不同的。
  4. 执行上下文

    • 每个进程都有自己的执行上下文,包括程序计数器、堆栈指针、寄存器集合等,这些上下文在进程切换时会保存和恢复。
  5. 文件描述符和文件权限

    • 进程对文件的访问是通过文件描述符进行的,操作系统通过文件权限来控制进程对文件的访问。
  6. 系统调用

    • 进程需要通过系统调用来请求操作系统提供的服务,如内存分配、文件操作等,这些系统调用会进行必要的安全检查。
  7. 用户和组ID

    • 每个进程都有一个用户ID(UID)和一个或多个组ID(GID),操作系统使用这些ID来控制进程对资源的访问权限。
  8. 命名空间

    • 现代操作系统(如Linux)使用命名空间来提供更细粒度的隔离,包括PID命名空间、网络命名空间、挂载命名空间等。
  9. 安全模块和沙箱

    • 操作系统和应用程序可以使用安全模块和沙箱技术来进一步限制进程的权限和行为。
  10. 权限控制

    • 进程的权限受到其用户权限和组权限的限制,操作系统会根据这些权限来控制进程可以执行的操作。
  11. AppArmor或SELinux

    • 这些是Linux系统中的强制访问控制系统,它们可以提供更细粒度的访问控制和隔离。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/5263.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.NET 解决Linux下Couldn‘t find a valid ICU package installed on the system异常的问题

最近使用.NET发布独立的Linux x64程序,在CentOS7.9的最小化安装系统上运行,结果运行不了,启动就报异常“Process terminated. Couldnt find a valid ICU package installed on the system. Please install libicu (or icu-libs) using your p…

3D,kd-tree算法原理

作为三维领域中一个重要的数据来源,点云主要是表征目标表面的海量点的集合,并不具备传统网格数据的几何拓扑信息,所以点云数据处理中最为核心的问题就是建立离散点间的拓扑关系,实现基于邻域关系的快速查找。 几何拓扑是计算几何学中的一个重要概念,指的是描述几何形状的空…

周三多《管理学原理》第3版/考研真题/章节练习题

普通高等教育“十一五”国家级规划教材《管理学原理》(第3版,周三多、陈传明、龙静编著,南京大学出版社)是我国高校广泛采用的管理学权威教材之一,也被众多高校(包括科研机构)指定为考研考博专业…

深度解析 Spring 源码:从BeanDefinition源码探索Bean的本质

文章目录 一、BeanDefinition 的概述1.1 BeanDefinition 的定位1.2 BeanDefition 的作用 二、BeanDefinition 源码解读2.1 BeanDefinition 接口的主要方法2.2 BeanDefinition 的实现类2.2.1 实现类的区别2.2.2 setBeanClassName()2.2.3 getDependsOn()2.2.4 setScope() 2.3 Bea…

触摸屏幕MSR BMS-2000维修三井主机遥控MITSUI EMS-200船舶电脑远程控制系统船用柴油主机遥控装置BMS-2000IIEMS-200II

远程控制系统 船用柴油主机遥控装置BMS-2000II&EMS-200II 该船用柴油机远程控制系统继承了已交付500多套的BMS-2000的理念,集成了新的电子技术。 曾为BMS-2000赢得好评的液晶显示屏进行了更新,并在W/H和C/R上作为标准安装。此外,备用控制…

关于修改hosts,浏览器并没有刷新生效的问题.

1.windows系统用cmd命令: ipconfig /flushdns 进行刷新.并查看本地解析是否已经刷新. 2.检查是否开了,代理,代理还是有影响的,关闭,不然不会生效 3.针对谷歌浏览器解决方案: 访问: chrome://net-internals/?#sockets 点击close idle sockets和flush socket pools,,,清…

2024年申请海外访问学者,需要注意些什么呢?

越来越多的国内医院对于医生职称晋升有海外经历要求,医生出于临床技能提高和科研思维拓展,自己也有海外进修的需求,并且可以了解世界先进医疗理念及科研进展,何乐而不为? 其实,很多医生已经赶上早班车,通…

AI大模型探索之路-实战篇2:基于CVP架构-企业级知识库实战落地

目录 前言 一、概述 二、本地知识库需求分析 1. 知识库场景分析 2. 知识库应用特点 3. 知识库核心功能 三、本地知识库架构设计 1. RAG架构分析 2. 大模型方案选型 3. 应用技术架构选型 4. 向量数据库选型 5. 模型选型 三、本地知识库RAG评估 四、本地知识库代码落地 1. 文件…

【QGIS如何进行WKT可视化】

点击插件——python控制台 渲染线图层wkt = LINESTRINGZ (405223.79236294992733746767 3294798.52338150842115283012 0, 405250.43677213048795238137 3294767.52838639216497540474 0, 405272.27118375105783343315 3294735.17657975200563669205 0, 405363.435978673573117…

新东方老师董宇辉直播间“买买买”,知识型员工培训有多重要?

近期,直播领域涌出了一股清流,那就是新东方老师董宇辉的直播间,在“买买买!”、“上链接”、“9.9包邮”、“买一包送五包”等等层出不穷的推货方式中,董宇辉别具一格的直播方式让大家眼前一亮。 “金句”频出&#x…

局域网屏幕桌面监控哪个软件比较好?哪款好用?

在企业、教育机构或其他组织中,出于提高工作效率、保障数据安全、规范员工行为等目的,对局域网内电脑屏幕进行实时监控的需求日益凸显。 面对市场上众多屏幕监控软件,选择一款功能全面、稳定可靠且符合法规要求的产品至关重要。 在局域网屏幕…

unity生成随机表元素间隔距离相同的点

#region 生成随机点 float minX -800f; float maxX 800f; float minY -400f; float maxY 400f; // 计算相邻点之间的间距 float distanceBetweenPoints 500f; // 生成指定数量的点…

【WEB前端2024】开源智体世界:乔布斯3D纪念馆-第15课-xcard方式跳转平行3D馆

【WEB前端2024】开源智体世界:乔布斯3D纪念馆-第15课-xcard方式跳转平行3D馆 使用dtns.network德塔世界(开源的智体世界引擎),策划和设计《乔布斯超大型的开源3D纪念馆》的系列教程。dtns.network是一款主要由JavaScript编写的智…

【C/C++】动态内存管理(C:malloc,realloc,calloc,free || C++:new,delete)

🔥个人主页: Forcible Bug Maker 🔥专栏: C | | C语言 目录 前言C/C内存分布C语言中的动态内存管理:malloc/realloc/realloc/freemallocrealloccallocfree C中的动态内存管理:new/deletenew和delete操作内…

华为校招机试 - 足球队员射门能力排序(20240424)

在线OJ测试 题目详情 - 足球队员射门能力排序 - HydroOJ 题目描述 球队有 n 个足球队员参与 m 次射门训练 每次射门进球用 1 表示,射失则用 0 表示,依据如下规则对该 n 个队员的射门能力做排序: 进球总数更多的队员射门能力更强若进球总数—样多,则比较最多—次连续进球…

港口数据复杂不知道如何监控?来试试FineVis所展现的智慧港口看板

一、智慧港口是什么 智慧港口代表着港口建设的未来趋势和发展方向。以信息物理系统为框架,智慧港口通过创新应用高新技术,实现了物流供给方和需求方之间的沟通,并将它们融入集疏运一体化系统中。这种系统极大地提升了港口及其相关物流园区对…

Python教程:使用psutil和rich库实现一个终端资源监控小工具(附完整代码)

在本文中,我们将介绍如何使用 Python 的 psutil 和 rich 库来实现一个终端资源监控小工具。psutil 是一个跨平台的 Python 库,用于获取关于系统进程和系统利用率的信息,而 rich 是一个 Python 库,用于在终端中创建美观的输出。 1.…

【LeetCode:1103. 分糖果 II + 模拟】

🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…

山东专升本计算机基础 --- Windows 10 操作系统安全

文章目录 Windows 10 操作系统安全1、Windows 10 系统安装的安全2、系统帐户安全3、应用安全策略4、网络安全策略 Windows 10 操作系统安全 1、Windows 10 系统安装的安全 操作系统的安全和安装操作系统的选项密切相关。 选择 NTFS 文件格式分区组件的定制安装 Windows 10 …

LiveCD镜像文件的定制化

最近想要定制化一款属于自己的LiveCD镜像文件,并且里边封装好所需要的软件程序,本文将会记录具体的操作步骤,供有需要的人参考借鉴。 环境说明: 环境配置说明配置参数编码环境Centos7.9LiveCD文件CentOS-7-livecd-x86_64.iso 附…