以下是针对 **D-Bus、Socket、Binder(Android)、mmap 和钩子(Hook)** 的 Python IPC 实现代码示例及解析:
---
### 一、D-Bus(Linux 桌面 IPC)
D-Bus 是 Linux 桌面环境的核心 IPC 机制,用于进程间通信(如系统服务与应用的交互)。
#### 1. **Python 实现(使用 `pydbus` 库)**
```bash
pip install pydbus
```
#### 2. **服务端(发布 D-Bus 服务)**
```python
from pydbus import SessionBus
from gi.repository import GLib
class CalculatorService:
dbus = """
<node>
<interface name='com.example.Calculator'>
<method name='Add'>
<arg type='i' name='a' direction='in'/>
<arg type='i' name='b' direction='in'/>
<arg type='i' name='result' direction='out'/>
</method>
</interface>
</node>
"""
def Add(self, a, b):
return a + b
bus = SessionBus()
bus.publish("com.example.Calculator", CalculatorService())
loop = GLib.MainLoop()
loop.run()
```
#### 3. **客户端(调用 D-Bus 服务)**
```python
from pydbus import SessionBus
bus = SessionBus()
proxy = bus.get("com.example.Calculator")
result = proxy.Add(10, 20)
print(f"Result: {result}") # 输出 30
```
#### **特点**
- 适用于 Linux 桌面环境(如 GNOME/KDE)
- 支持信号(Signal)、方法(Method)、属性(Property)等复杂交互
---
### 二、Socket(跨平台 IPC)
Socket 是最通用的 IPC 方式,支持跨平台通信。
#### 1. **TCP Socket 示例**
```python
# 服务端
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 12345))
s.listen(1)
conn, addr = s.accept()
data = conn.recv(1024)
print(f"Received: {data.decode()}")
conn.send(b"Hello from Server")
conn.close()
# 客户端
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 12345))
s.send(b"Hello from Client")
response = s.recv(1024)
print(f"Server Response: {response.decode()}")
s.close()
```
#### 2. **Unix Domain Socket(高性能本地通信)**
```python
# 服务端
import socket, os
sock_path = '/tmp/uds.sock'
if os.path.exists(sock_path):
os.unlink(sock_path)
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.bind(sock_path)
s.listen(1)
conn, _ = s.accept()
data = conn.recv(1024)
conn.send(b"Ack via Unix Socket")
conn.close()
# 客户端
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect('/tmp/uds.sock')
s.send(b"Hello via Unix Socket")
print(s.recv(1024).decode())
s.close()
```
---
### 三、Binder(Android 专用 IPC)
Binder 是 Android 特有的 IPC 机制,标准 Python 无法直接使用,但可通过以下方式实现:
#### 1. **通过 Android NDK + Python 绑定(复杂方案)**
需编写 C/C++ Binder 服务并通过 Python 的 `ctypes` 调用:
```python
# 假设已编译 libbinder.so
from ctypes import CDLL, c_char_p
lib = CDLL('./libbinder.so')
lib.init_binder_service.restype = c_char_p
# 调用 Binder 服务
response = lib.call_binder_method(b"get_data")
print(f"Binder Response: {response.decode()}")
```
#### 2. **替代方案(使用 Android 的 `aidl` 工具)**
- 定义 AIDL 接口文件(`IMyService.aidl`)
- 生成 Java 服务端/客户端代码
- 通过 `pyjnius` 调用 Java 代码:
```python
from jnius import autoclass
MyService = autoclass('com.example.MyService')
service = MyService()
result = service.getResult(10, 20)
print(f"Binder Result: {result}")
```
---
### 四、共享内存(mmap)
通过内存映射文件实现高速数据共享。
#### **Python 代码示例**
```python
# 进程 A(写入)
import mmap, os
shm_fd = os.open('/dev/shm/mmap_example', os.O_CREAT | os.O_RDWR)
os.ftruncate(shm_fd, 1024) # 分配 1KB
shm = mmap.mmap(shm_fd, 1024, access=mmap.ACCESS_WRITE)
shm.write(b"Data from Process A")
shm.close()
# 进程 B(读取)
shm_fd = os.open('/dev/shm/mmap_example', os.O_RDONLY)
shm = mmap.mmap(shm_fd, 1024, access=mmap.ACCESS_READ)
data = shm.read(1024).strip(b'\x00')
print(f"Read: {data.decode()}")
shm.close()
os.unlink('/dev/shm/mmap_example')
```
#### **同步优化(添加信号量)**
```python
import posix_ipc # pip install posix_ipc
# 创建信号量
sem = posix_ipc.Semaphore(
"/mmap_semaphore",
flags=posix_ipc.O_CREAT,
initial_value=1
)
# 进程 A(写入前加锁)
sem.acquire()
shm.write(b"Atomic Data")
sem.release()
# 进程 B(读取前加锁)
sem.acquire()
data = shm.read(1024)
sem.release()
```
---
### 五、钩子(Hook)
通过拦截系统调用或函数实现 IPC 监控。
#### 1. **Python 函数钩子(装饰器)**
```python
def hook_function(original_func):
def wrapper(*args, **kwargs):
print(f"Hooked: {original_func.__name__}")
return original_func(*args, **kwargs)
return wrapper
# 示例:钩住 socket.send()
import socket
original_send = socket.socket.send
socket.socket.send = hook_function(original_send)
s = socket.socket()
s.connect(('localhost', 80))
s.send(b"GET / HTTP/1.1\r\n") # 触发钩子输出
```
#### 2. **LD_PRELOAD 钩子(C 扩展)**
通过 C 库拦截系统调用:
```c
// hook.c
#include <stdio.h>
#include <dlfcn.h>
ssize_t send(int sockfd, const void *buf, size_t len, int flags) {
printf("Hook: Data sent via socket %d\n", sockfd);
ssize_t (*original_send)(int, const void*, size_t, int) = dlsym(RTLD_NEXT, "send");
return original_send(sockfd, buf, len, flags);
}
```
编译并注入:
```bash
gcc -shared -fPIC -o libhook.so hook.c -ldl
LD_PRELOAD=./libhook.so python3 my_script.py
```
---
### 六、性能对比与选择建议
| 机制 | 适用场景 | 性能 | 复杂度 | 跨平台性 |
|------------|---------------------------|-------|--------|----------------|
| **D-Bus** | Linux 桌面服务通信 | 中 | 高 | Linux 专用 |
| **Socket** | 通用网络/本地通信 | 中高 | 低 | 全平台 |
| **Binder** | Android 系统级通信 | 高 | 极高 | Android 专用 |
| **mmap** | 高速大数据共享 | 极高 | 中 | 类 Unix 系统 |
| **Hook** | 监控/修改系统行为 | 依赖 | 极高 | 依赖钩子实现 |
#### **建议**
- 优先选择 **Unix Domain Socket**(本地通信)或 **mmap**(高性能共享内存)
- Android 环境使用 **Binder**(需结合 Java/NDK)
- 需要监控 IPC 行为时使用 **Hook**(调试或安全场景)