为什么Linux可以在多处理中接受套接字?

Goo*_*ies 10 python sockets linux python-multiprocessing

此代码在Linux上运行良好,但在Windows下失败(预期).我知道多处理模块用于fork()生成一个新进程,因此父进程拥有的文件描述符(即打开的套接字)由子进程继承.但是,我的理解是,您可以通过多处理发送的唯一类型的数据需要是可选择的.在Windows和Linux上,套接字对象不是pickleable.

from socket import socket, AF_INET, SOCK_STREAM
import multiprocessing as mp
import pickle

sock = socket(AF_INET, SOCK_STREAM)
sock.connect(("www.python.org", 80))
sock.sendall(b"GET / HTTP/1.1\r\nHost: www.python.org\r\n\r\n")

try:
    pickle.dumps(sock)
except TypeError:
    print("sock is not pickleable")

def foo(obj):
    print("Received: {}".format(type(obj)))
    data, done = [], False
    while not done:
        tmp = obj.recv(1024)
        done = len(tmp) < 1024
        data.append(tmp)
    data = b"".join(data)
    print(data.decode())


proc = mp.Process(target=foo, args=(sock,))
proc.start()
proc.join()
Run Code Online (Sandbox Code Playgroud)

我的问题是为什么一个socket对象,一个明显不可拾取的对象,可以通过多处理传递?是不是像Windows那样使用泡菜?

mat*_*ata 6

在unix平台上,可以使用unix域(AF_UNIX)套接字将套接字和其他文件描述符发送到不同的进程,因此可以在多处理的上下文中对套接字进行pickle.

多处理模块使用特殊的pickler实例而不是常规的pickler,ForkingPickler来pickle套接字和文件描述符,然后可以在不同的进程中进行unpickled.这是唯一可能的,因为已知pickle实例将被打开的地方,挑选一个套接字或文件描述符并在机器边界之间发送它是没有意义的.

对于Windows ,打开文件句柄有类似的机制.