python中的克隆进程支持
Python中是否支持系统调用(而不是python中的克隆进程支持,python,Python,Python中是否支持系统调用(而不是os.fork)?我想在Python下使用Linux名称空间,但似乎没有太多关于它的信息 编辑: 我认为使用libc的ctypes是答案,但我仍然没有取得任何成功。fork可以正常工作,因为它没有任何参数,所以下面的代码可以工作: from ctypes import * libc = CDLL("libc.so.6") libc.fork() 使用clone,我正在尝试以下操作: from ctypes import * def f(): p
os.fork
)?我想在Python下使用Linux名称空间,但似乎没有太多关于它的信息
编辑:
我认为使用libc的ctypes是答案,但我仍然没有取得任何成功。fork可以正常工作,因为它没有任何参数,所以下面的代码可以工作:
from ctypes import *
libc = CDLL("libc.so.6")
libc.fork()
使用clone,我正在尝试以下操作:
from ctypes import *
def f():
print "In callback."
return 0
libc = CDLL("libc.so.6")
f_c = CFUNCTYPE(c_int)(f)
print libc.getpid()
print libc.clone(f_c)
print get_errno()
克隆实际上具有以下签名:
int克隆(int(*fn)(void*),void*子堆栈,
整型标志,无效参数。。。
/pid_t*ptid、结构用户_desc*tls、pid_t*ctid*/)
我仍然需要传递*child_堆栈和标志,但不知道如何做。有什么帮助吗
更多编辑:
我现在明白了:
from ctypes import *
def f():
print "In callback."
return 0
libc = CDLL("libc.so.6")
f_c = CFUNCTYPE(c_int)(f)
stack = c_char_p(" " * 1024 * 1024)
libc.clone(f_c, c_void_p(cast(stack, c_void_p).value + 1024 * 1024), 0)
这实际上是可行的,但我想象我用堆栈在我的系统上打了一个大洞,有没有更干净的方法呢
编辑:
即将完成,为newpid添加正确的标志:
from ctypes import *
libc = CDLL("libc.so.6")
def f():
print libc.getpid()
return 0
f_c = CFUNCTYPE(c_int)(f)
stack = c_char_p(" " * 1024 * 1024)
libc.clone(f_c, c_void_p(cast(stack, c_void_p).value + 1024 * 1024), 0x20000000)
这不仅仅是为root用户运行的,并且打印一个漂亮的1
在这篇文章之后,堆栈似乎很好:嗯,最后我想我得到了答案,就是使用libc 这是一个简单的概念证明:
from ctypes import *
libc = CDLL("libc.so.6")
# Create stack.
stack = c_char_p(" " * 8096)
def f():
print libc.getpid()
return 0
# Conver function to c type returning an integer.
f_c = CFUNCTYPE(c_int)(f)
# We need the top of the stack.
stack_top = c_void_p(cast(stack, c_void_p).value + 8096)
# Call clone with the NEWPID Flag
libc.clone(f_c, stack_top, 0x20000000)
这必须由root用户运行。如果您希望具有“fork()但具有新名称空间”语义,可以直接调用SYS\u clone
syscall。请注意,如果这样做,则os.getpid()
方法将在子进程中返回错误的进程ID,因为glibc缓存进程ID,并且不知道调用SYS\u clone
使其缓存无效
假设x86_64(
NR_clone==56
,NR_getpid==39
),您可以调用libc.syscall(56,signal.sigchd | 0x000200000,0 0)
到“fork”,然后libc.syscall(39)
来获取“forked”子进程的当前PID。如果您只使用clone\u NEWPID
标志(0x000200000
),子进程将立即重新租给父进程的init,因此父进程将无法等待子进程。如果要在父进程中等待子进程,可能需要使用signal.SIGCHLD | 0x000200000
。(您必须指定一些信号,SIGCHLD
是明显的候选者。)“从glibc 2.3.4版到2.24版,用于getpid()缓存PID的glibc包装函数,……自glibc 2.25版以来,PID缓存被删除:对getpid()的调用总是调用实际的系统调用,而不是返回缓存值。”()