2016-05-04 87 views
12

我想在Python中創建syscall,並且該函數不在libc中,有沒有辦法在Python中執行?在Python中進行系統調用

更具體地說,我想打電話給getdents,其手冊頁說

注:對於這些系統調用的glibc沒有包裝;

所有現有的相關解決方案我發現在網絡上使用​​與libc.so:爲example

請不要質疑爲什麼我想直接使用getdents,我有一個非常具體的理由來做到這一點,並且在這個問題上討論會很讓人分心。謝謝。

回答

12

暴露libc庫的函數調用「定製」的系統調用:long syscall(long number, ...);

syscall()是一個小型的庫函數調用系統調用 其彙編語言界面與 指定的參數指定number。在調用C 庫中沒有包裝函數的系統調用時,使用syscall()很有用,例如, 。

剛剛接觸像任何外國功能這一功能:

import ctypes 

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

例如

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

或者翻譯的手冊頁的例子:

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