2012-11-14 46 views
8

Python中是否支持syscall clone(2)而不是os.fork)?我想在Python下使用Linux命名空間,但似乎沒有很多關於它的信息。python中的克隆進程支持

編輯:

我覺得跟libc中的ctypes是答案,但我仍然沒有任何成功。叉工程沒有問題,因爲它沒有任何參數,那麼此代碼的工作:

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和標誌,但不知道如何去做。任何幫助?

多個編輯:

我得到這個現在:

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) 

這是不可運行只是爲根,並打印一份漂亮的1

並且在這之後發佈堆棧似乎很好:http://code.google.com/p/chromium/wiki/LinuxPidNamespaceSupport

+2

如果只使用'CLONE_NEWPID'標誌('0x000200000'),子進程會立即重新映射到父進程的init,所以父進程將無法等待子進程。如果您想等待父進程中的子進程,您可能需要使用'signal.SIGCHLD | 0x000200000'。 (你必須指定一些信號,'SIGCHLD'是顯而易見的候選。) – mkj

回答

6

那麼,最後我想我得到了答案,只是用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運行。

0

如果您希望擁有「fork()但具有新名稱空間」語義,則可以直接調用SYS_clone系統調用。請注意,如果這樣做,那麼os.getpid()方法將在子項中返回錯誤的進程標識,因爲glibc會緩存進程標識並且不知道調用將使其緩存失效。

假設x86_64的(NR_clone == 56NR_getpid == 39),你可以打電話給libc.syscall(56, signal.SIGCHLD|0x000200000, 0 0 0)「叉」,然後libc.syscall(39)獲得「分叉」的子進程的當前PID。