12

Python でsyscall clone(2)( not ) のサポートはありますか? os.forkPython で 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 だけでは実行できず、nice 1 を出力します。

そして、この投稿に続いて、スタックは問題ないようです: http://code.google.com/p/chromium/wiki/LinuxPidNamespaceSupport

4

2 に答える 2

9

さて、ようやく答えが出たと思います.libcでctypesを使用するだけです.

これは、概念の簡単な証明です。

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 で実行する必要があります。

于 2012-11-14T07:34:27.067 に答える
1

「fork() が新しい名前空間を持つ」セマンティクスが必要な場合は、SYS_clone代わりに syscall を直接呼び出すことができます。これを行うと、glibc はプロセス ID をキャッシュし、そのキャッシュを無効にos.getpid()する呼び出しを認識しないため、メソッドは子で間違ったプロセス ID を返すことに注意してください。SYS_clone

x86_64 ( NR_clone == 56, ) を想定すると、「fork」NR_getpid == 39を呼び出して、「fork」された子プロセスの現在の PID を取得できます。libc.syscall(56, signal.SIGCHLD|0x000200000, 0 0 0)libc.syscall(39)

于 2013-05-08T01:58:52.407 に答える