2009-04-17 15 views
2

Ich habe folgenden CodePython ctypes und Sysctl

import sys 
from ctypes import * 
from ctypes.util import find_library 

libc = cdll.LoadLibrary(find_library("c")) 
CTL_KERN = 1 
KERN_SHMMAX = 34 
sysctl_names = { 
    'memory_shared_buffers' : (CTL_KERN, KERN_SHMMAX), 
    } 

def posix_sysctl_long(name): 
    _mem = c_uint64(0) 
    _arr = c_int * 2 
    _name = _arr() 
    _name[0] = c_int(sysctl_names[name][0]) 
    _name[1] = c_int(sysctl_names[name][1]) 
    result = libc.sysctl(_name, byref(_mem), c_size_t(sizeof(_mem)), None, c_size_t(0)) 
    if result != 0: 
     raise Exception('sysctl returned with error %s' % result) 
    return _mem.value 

print posix_sysctl_long('memory_shared_buffers') 

das folgende Ergebnis liefert:

Traceback (most recent call last): 
    File "test.py", line 23, in <module> 
    print posix_sysctl_long('memory_shared_buffers') 
    File "test.py", line 20, in posix_sysctl_long 
    raise Exception('sysctl returned with error %s' % result) 
Exception: sysctl returned with error -1 

ich gues ich habe etwas falsch gemacht. Was wäre die richtige Aufrufkonvention? Wie würde ich herausfinden, was genau falsch gelaufen ist?

Antwort

6

Sie geben der sysctl-Funktion nicht die richtigen Werte. Detaillierte Informationen zu den Argumenten von sysctl() finden Sie unter here.

Hier sind Ihre Fehler:

  • Sie die nLen Argument (zweites Argument) vergessen haben
  • Die oldlenp Argument ist ein Zeiger auf die Größe, die nicht direkt die Größe

Hier ist die korrekte Funktion (mit geringfügiger Verbesserung):

def posix_sysctl_long(name): 
    _mem = c_uint64(0) 
    _def = sysctl_names[name] 
    _arr = c_int * len(_def) 
    _name = _arr() 
    for i, v in enumerate(_def): 
     _name[i] = c_int(v) 
    _sz = c_size_t(sizeof(_mem)) 
    result = libc.sysctl(_name, len(_def), byref(_mem), byref(_sz), None, c_size_t(0)) 
    if result != 0: 
     raise Exception('sysctl returned with error %s' % result) 
    return _mem.value 
+0

Vielen Dank. In der Tat, irgendwie habe ich den zweiten Parameter vergessen :-( Meine ursprüngliche Version verwendet sysctlbyname, da der Parameter nicht benötigt wird. Leider scheint es, dass Linux diese Funktion nicht unterstützt. – Mauli