2016-05-04 60 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