【问题标题】:Make syscall in Python在 Python 中进行系统调用
【发布时间】:2016-08-30 03:44:03
【问题描述】:

我想在 Python 中创建 syscall 并且函数不在 libc 中,有没有办法在 Python 中实现?

更具体地说,我想致电getdents,其手册页显示

注意:这些系统调用没有 glibc 包装器;

我在网上找到的所有现有相关解决方案都使用ctypeslibc.so: for example

请不要质疑我为什么要直接使用getdents,我这样做有一个非常具体的原因,在这个问题上讨论会分散注意力。谢谢。

【问题讨论】:

    标签: python python-2.7 system-calls


    【解决方案1】:

    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
    

    或翻译手册页中的示例:

    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
    

    【讨论】:

    • 此策略_getdents = ctypes.CDLL(None).syscall 是否可重复使用。假设您想要getdents 和其他一些syscall,它们需要一组不同的参数。您可以创建另一个syscall 的副本,然后将argtypes 修改为其他内容吗?还是anotherfun = ctypes.CDLL(None).syscall_getdents 引用相同的对象,因此修改argtypes 也会修改_getdents 的argtypes?
    • @cheshirekow 真是个奇怪的巧合...我现在只是在自己查一下,在您问了一个 3 岁的问题 10 小时后... AFAICT 的答案是一个电话到CDLL 你只能设置argtypes 一次。但是如果你调用CDLL(None)两次,你可以在每个副本上分别设置dll.syscall.argtypes
    猜你喜欢
    • 2011-03-29
    • 2012-02-12
    • 1970-01-01
    • 2014-11-04
    • 2017-04-17
    • 2012-06-19
    • 2021-08-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多