之前遇到一个问题,需要将场景服务这个模块拆分出来,用独立的一个线程去执行。使用独立的线程好处就是,逻辑写的可以相对简单粗暴点,不必考虑到大量的场景服务逻辑卡主线程的情况。

由于我们服务器之前是使用python作为脚本开发,而大家都知道的python有个gil,这意味着并发的线程里只有一个可以获得解释器的全局锁,从而并执行python代码。当然了python这样子也是有原因的,由于其内部使用了大量的静态变量,因此多线程环境下必须有一个线程同步的机制。结果最后选择了在服务器又再嵌入了一个(多个)lua虚拟机,把场景服务用lua来写。

但是,实际上我们是可以做到在一个进程内做到并行的运行多个python虚拟机的,只不过过程稍微曲折一点。基本的思想就是,重复导入多份python动态链接库,每个线程上运行完全独立的python代码

在Linux下就可以通过dlopen运行时动态的导入一个so模块,使用dlmopen则可以重复的导入多份相同的so。dlopen:https://docs.oracle.com/cd/E23824_01/html/821-1465/dlmopen-3c.html#scrolltoc

windows下则不得不在文件系统上保存多份python.dll的实例,并且在运行时通过LoadLibrary分别导入这些dll。LoadLibrary:https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms684175(v=vs.85).aspx

基于上述思路我大致简单实现了一下:

https://github.com/adinosaur/python-vm

有几点要说明的是:

调用Py_Initialize初始化python以及后续调用其它cpython的api必须在同一个线程内,否则在debug版的python中会报没有获得解释器锁而调用cpython api的错误,从而终止程序。

调用动态链接库里的函数这部分代码需要特别注意,虽然在熟知动态连接库使用的调用约定后(比如gcc可能是cdecl,msvc可能是stdcall),是可以将这部分代码写的十分精简通用的。但因为目前我还没做到,因此选择了保守的枚举法:)

linux下使用dlmopen导入多份libpython.so,执行时会有段错误,具体原因尚未查明。因此我的实现中在linux下也是像windows那样,在文件系统中存多份动态链接库的实例。

参考连接:

https://stackoverflow.com/questions/1745975/load-multiple-copies-of-a-shared-library

并行运行多个python虚拟机的更多相关文章

  1. python虚拟机运行原理

    近期为了面试想要了解下python的运行原理方面的东西,奈何关于python没有找到一本类似于深入理解Java虚拟机方面的书籍,找到了一本<python源码剖析>电子书,但是觉得相对来说最 ...

  2. python 虚拟机是单线程;当线程执行I/O密集型操作是,ce

    python 虚拟机是单线程:当线程执行I/O密集型操作是 单核CPU,不存在“并行”,与语言无关:每个线程运行中,其他线程等待该线程让步 粗粒度的并行 靠 软件,细---硬---

  3. python虚拟机中的异常流控制

    异常:对程序运行中的非正常情况进行抽象.并且提供相应的语法结构和语义元素,使得程序员能够通过这些语法结构和语义元素来方便地描述异常发生时的行为. 1.Python中的异常机制: 1.1Python虚拟 ...

  4. Cobra —— 可视化Python虚拟机 and 图解python

    http://blog.csdn.net/balabalamerobert http://blog.csdn.net/efeics/article/category/1486515  图解python ...

  5. 《python源代码剖析》笔记 python虚拟机中的函数机制

    本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.Python虚拟机在运行函数调用时会动态地创建新的 PyFrameObject对象, 这 ...

  6. Python虚拟机类机制之instance对象(六)

    instance对象中的__dict__ 在Python虚拟机类机制之从class对象到instance对象(五)这一章中最后的属性访问算法中,我们看到“a.__dict__”这样的形式. # 首先寻 ...

  7. Python虚拟机类机制之从class对象到instance对象(五)

    从class对象到instance对象 现在,我们来看看如何通过class对象,创建instance对象 demo1.py class A(object): name = "Python&q ...

  8. Python虚拟机类机制之自定义class(四)

    用户自定义class 在本章中,我们将研究对用户自定义class的剖析,在demo1.py中,我们将研究单个class的实现,所以在这里并没有关于继承及多态的讨论.然而在demo1.py中,我们看到了 ...

  9. Python虚拟机类机制之descriptor(三)

    从slot到descriptor 在Python虚拟机类机制之填充tp_dict(二)这一章的末尾,我们介绍了slot,slot包含了很多关于一个操作的信息,但是很可惜,在tp_dict中,与__ge ...

随机推荐

  1. centos 7下ldap安装

    环境说明: 操作系统:CentOS Linux release 7.5.1804 (Core) LDAP:2.4.44 前提条件: 关闭防火墙.selinux,同时进行时钟同步. 其中XXX需要用域名 ...

  2. 学习Spring Boot:(三)配置文件

    前言 Spring Boot使用习惯优于配置(项目中存在大量的配置,此外还内置了一个习惯性的配置,让你无需手动进行配置)的理念让你的项目快速运行起来. 正文 使用配置文件注入属性 Spring Boo ...

  3. BZOJ 2844: albus就是要第一个出场

    2844: albus就是要第一个出场 Time Limit: 6 Sec  Memory Limit: 128 MBSubmit: 1134  Solved: 481[Submit][Status] ...

  4. 【Cf #290 B】Fox And Jumping(dp,扩展gcd)

    根据裴蜀定理,当且仅当选出来的集合的L[i]的gcd等于1时,才能表示任何数. 考虑普通的dp,dp[i][j]表示前i个数gcd为j的最少花费,j比较大,但状态数不多,拿个map转移就好了. $ \ ...

  5. keepalived回顾

    Keepalived是lvs的扩展项目,因此它们之间具备良好的兼容性. 通过对服务器池对象的健康检查,实现对失效机器/服务的故障隔离: 负载均衡器之间的失败切换failover,通过VRRPv2 st ...

  6. golang管道

    golang中的channel channel用于goroutine之间的通信 如果不用channel,使用共享全局变量的方式,需要加锁 // synchornized 同步 // golang中的 ...

  7. python---协程理解

    推文:python---基础知识回顾(七)迭代器和生成器 推文:Python协程深入理解(本文转载于该文章) 从语法上来看,协程和生成器类似,都是定义体中包含yield关键字的函数.yield在协程中 ...

  8. [非常重要的总结] Linux C相关函数

    (1)字符测试函数 isalnum(测试字符是否为英文字母或数字) isalpha(测试字符是否为英文字母) isascii(测试字符是否为ASCII码字符) isblank(测试字符是否为空格字符) ...

  9. NGINX生产环境反向代理到后端tomcat配置

    #当访问www.kazihuo.com//sichuan-user-te时,跳转到http://10.1.93.61:7005/sichuan-user server { listen ; serve ...

  10. Centos7一键编译安装zabbix-4.0.2

    ##只针对centos7的系统有效,centos6无效,mysql zabbix用户:zabbix,密码:zabbix;建议用全新的centos7服务器 软件版本: (nginx-1.14.2.php ...