2016-05-04 4 views
12

私はsyscallをPythonで作っていますが、その機能はlibcにはありません。Pythonでそれを行う方法はありますか?Pythonでsyscallを作成する

は具体的には、私は、そのマニュアルページ

注意が言う、getdentsを呼び出したい:これらのシステムコールにはglibcのラッパーはありません。私はウェブ上で発見

すべての既存の関連ソリューションはlibc.soと​​使用しています:exampleため。

なぜ私はgetdentsを直接使用したいのか疑問に思ってはいけません。私はそれを行うための非常に具体的な理由があり、この質問で議論するのは気にならないでしょう。ありがとうございました。

答えて

12

libcのは、「カスタム」のシステムコールを呼び出すための機能を公開します。long syscall(long number, ...);

syscall()は、アセンブリ言語インタフェース 指定された引数でnumberを指定したシステムコール を呼び出す小さなライブラリ関数です。 syscall()を使用すると、C ライブラリでラッパー機能を持たないシステムコールを呼び出すときには、 などの便利な機能が使用できます。

だけで任意の外部関数のように、この機能にアクセスします。

import ctypes 

libc = ctypes.CDLL(None) 
syscall = libc.syscall 

例えば

syscall(39) # 39 = getpid, but you get the gist 

またはmanページの例を翻訳する:

import os, ctypes 

off_t = ctypes.c_long # YMMV 
__NR_getdents = 78 # YMMV 

class linux_dirent(ctypes.Structure): 
    _fields_ = [ 
     ('d_ino', ctypes.c_long), 
     ('d_off', off_t), 
     ('d_reclen', ctypes.c_ushort), 
     ('d_name', ctypes.c_char) 
    ] 

_getdents = ctypes.CDLL(None).syscall 
_getdents.restype = ctypes.c_int 
_getdents.argtypes = ctypes.c_long, ctypes.c_uint, ctypes.POINTER(ctypes.c_char), ctypes.c_uint 

fd = os.open('/tmp/', os.O_RDONLY | os.O_DIRECTORY) 

buf = ctypes.ARRAY(ctypes.c_char, 1024)() 
while True: 
    nread = _getdents(__NR_getdents, fd, buf, len(buf)) 
    if nread == -1: 
     raise OSError('getdents') 
    elif nread == 0: 
     break 

    pos = 0 
    while pos < nread: 
     d = linux_dirent.from_buffer(buf, pos) 

     name = buf[pos + linux_dirent.d_name.offset : pos + d.d_reclen] 
     name = name[:name.index('\0')] 
     print 'name:', name 

     pos += d.d_reclen 
関連する問題