Python中是否支持系统调用clone(2)
(不 os.fork
)?我想在Python下使用Linux命名空间,但似乎没有很多关于它的信息。
编辑:
我认为使用libc的ctypes是答案,但我仍然没有取得任何成功。 fork工作没有问题,因为它没有任何参数,然后这段代码工作:
from ctypes import *
libc = CDLL("libc.so.6")
libc.fork()
克隆我试试这个:
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 clone(int(* fn)(void *),void * child_stack, int flags,void arg,... / pid_t * ptid,struct user_desc * tls,pid_t * ctid * /);
我仍然需要传递* child_stack和flags但不知道该怎么做。有什么帮助吗?
更多编辑:
我现在得到了这个:
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。
在这篇文章之后,堆栈看起来很好:http://code.google.com/p/chromium/wiki/LinuxPidNamespaceSupport
答案 0 :(得分:8)
好吧,最后我想我得到了答案,就是将ctypes与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运行。
答案 1 :(得分:1)
如果你想拥有“fork()但是有新的命名空间”语义,你可以直接调用SYS_clone
系统调用。请注意,如果这样做,os.getpid()
方法将在子级中返回错误的进程ID,因为glibc会缓存进程ID,并且不知道SYS_clone
调用以使其缓存无效。
假设x86_64(NR_clone == 56
,NR_getpid == 39
),您可以将libc.syscall(56, signal.SIGCHLD|0x000200000, 0 0 0)
调用为“fork”,然后调用libc.syscall(39)
以获取“分叉”子项的当前PID过程