python实现win和linux的进程通信

因为之前写的pyqt程序涉及进程间交互内容,而win和linux选择的交互方式有所不同,因此这里记录一下传输的方法

Linux系统

linux系统进程间交互有很多方法,包括共享内存,信号传递等。由于我的程序功能比较简单,选择了发送信号的方法,但是发送信号有一个缺点,就是无法传输数据,只能触发事件,而且linux可选的信号也有限

可以通过 # kill -l 命令查看可用的信号

# kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

可以看到从34到往后的信号才是可用的,其他信号都为系统规定好的信号,下面是信号的例子

接收者:

import signal

def func():
    print("42信号被触发")
    
signal.signal(42, func)   # func为自定义函数,当42信号被触发时,程序执行的进程

while True:  # 需要开启循环,否则程序会自动退出
    pass

发送者:

import os    
import signal    
     
#发送信号,12344是前面接受者的pid,需要自行修改  
os.kill(12344, 42)

这样就实现了简单的多进程交互的动作。

Win系统

win系统提供了多种方法进行进程间通信,我这里选择了WM_COPYDATA消息方法(具体原理见官网),好处是可以传输字符串的信息,可以不用依赖文件什么的做信号的中转了,就是针对python的通信方法几乎没有,查了半天,照着c++实现了一个能用的:

信号监听:

import ctypes
import ctypes.wintypes
import win32api
import win32con
import win32gui


class COPYDATASTRUCT(ctypes.Structure):
    _fields_ = [
        ('dwData', ctypes.wintypes.LPARAM),
        ('cbData', ctypes.wintypes.DWORD),
        ('lpData', ctypes.c_void_p)
    ]


PCOPYDATASTRUCT = ctypes.POINTER(COPYDATASTRUCT)


class Listener:
    def __init__(self):
        WindowName ="CopyDataName"      # 这里规定句柄的名称,方便发送者找到对应的接收者
        message_map = {
            win32con.WM_COPYDATA: self.OnCopyData
        }
        wc = win32gui.WNDCLASS()
        wc.lpfnWndProc = message_map
        wc.lpszClassName = WindowName
        hinst = wc.hInstance = win32api.GetModuleHandle(None)
        classAtom = win32gui.RegisterClass(wc)
        self.hwnd = win32gui.CreateWindow(
            classAtom,
            "test",
            0,
            0,
            0,
            win32con.CW_USEDEFAULT,
            win32con.CW_USEDEFAULT,
            0,
            0,
            hinst,
            None
        )
        print("当前句柄", self.hwnd)

    def OnCopyData(self, hwnd, msg, wparam, lparam):
        pCDS = ctypes.cast(lparam, PCOPYDATASTRUCT)
        s = ctypes.string_at(pCDS.contents.lpData).decode()
        print(f"收到来自句柄{hwnd}的消息:{s}")
        return 1


l = Listener()
win32gui.PumpMessages()

信号发送:

import ctypes.wintypes

import win32con

FindWindow = ctypes.windll.user32.FindWindowW
SendMessage = ctypes.windll.user32.SendMessageW


class COPYDATASTRUCT(ctypes.Structure):
    _fields_ = [
        ('dwData', ctypes.wintypes.LPARAM),
        ('cbData', ctypes.wintypes.DWORD),
        ('lpData', ctypes.c_char_p)
    ]


# 通过寻找窗口名获取句柄
hwnd = FindWindow('CopyDataName', None)
print(hwnd)
# 或者直接根据句柄来发送
# hwnd = 1707560
cds = COPYDATASTRUCT()
cds.dwData = 0
msg = "这是通过VM_COPYDATA发送的数据"
msg_bytes = msg.encode('utf-8')
cds.cbData = ctypes.sizeof(ctypes.create_string_buffer(msg_bytes))
cds.lpData = ctypes.c_char_p(msg_bytes)
SendMessage(hwnd, win32con.WM_COPYDATA, 0, ctypes.byref(cds))

print("已发送CopyData数据", msg)

发送信号后,接收端的终端显示如下:

2295294
已发送CopyData数据 这是通过VM_COPYDATA发送的数据
posted @   聚乙烯  阅读(292)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· winform 绘制太阳,地球,月球 运作规律
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示