2016-05-04 19 views
12

Python'da syscall yapmak istiyorum ve işlev libc'da değil, Python'da bunu yapmanın bir yolu var mı?Python'da syscall yapın

Daha spesifik olarak, Kimin manpage

Not diyor getdents çağırmak istiyorum: Bu sistem çağrıları için hiçbir glibc sarmalayıcıları vardır; Web'de bulunan

Mevcut tüm ilgili çözümler libc.so ile ctypes kullanır: example için.

Lütfen neden getdents numaralı telefonu kullanmak istediğimi sormayın, bunu yapmak için çok özel bir nedenim var ve bu soruda tartışmak rahatsız edici olabilir. Teşekkür ederim.

cevap

12

Libc "Özel" syscalls çağırmak için bir işlev sunar: long syscall(long number, ...);

syscall() montaj dil arayüzü belirtilen bağımsız değişkenlerle number belirlemiştir sistem çağrısı çağıran küçük bir kütüphane fonksiyonudur. C kitaplığında sarıcı işlevi olmayan bir sistem çağrısını çağırırken syscall() kullanılması yararlıdır, örneğin .

Sadece herhangi bir yabancı fonksiyonu gibi bu fonksiyonu erişmek:

import ctypes 

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

örn

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

Ya adam sayfasında örnek çevirmek için:

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