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发送的数据
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· winform 绘制太阳,地球,月球 运作规律
· 上周热点回顾(3.3-3.9)