用Pythons ctypes从libc调用uname

2024-10-04 11:35:21 发布

您现在位置:Python中文网/ 问答频道 /正文

tl;dr

这适用于GNU版本的libc(还没有尝试过uclibc)

from ctypes import *

libc = CDLL('libc.so.6')

class uts_struct(Structure):
    _fields_ = [ ('sysname', c_char * 65),
                 ('nodename', c_char * 65),
                 ('release', c_char * 65),
                 ('version', c_char * 65),
                 ('machine', c_char * 65),
                 ('domain', c_char * 65) ]

gnar = uts_struct()

libc.uname(byref(gnar))

print gnar.nodename

原岗位

以下代码段错误;我不确定我做错了什么。在

^{pr2}$

这样做是一样的:

from ctypes import *

libc = CDLL('libc.so.6')

class uts_struct(Structure):
    _fields_ = [ ('sysname', c_char_p),
                 ('nodename', c_char_p),
                 ('release', c_char_p),
                 ('version', c_char_p),
                 ('machine', c_char_p) ]

utsname = uts_struct()
utsname_pointer = pointer(utsname)
libc.uname(utsname_pointer)

print utsname.sysname

我一定是搞砸了一些基本的东西。。。在

(我知道os.uname(),这只是一个理解的练习,我失败了)

我在这里引用了uname手册:http://www.cl.cam.ac.uk/cgi-bin/manpage?2+uname

我做错什么了?在


编辑:

多亏了Nemo我能够得到数据

>>> from ctypes import *
>>> libc = CDLL('libc.so.6')
>>> gnar = create_string_buffer(512)
>>> libc.uname(byref(gnar))
0
>>> print gnar.value
Linux
>>> 

但是,我假设我只得到'Linux',因为这些项是空分隔的,调节器字符串也是。有没有办法读过空值?在


编辑2:

根据Nemos的评论,我试过这个-这不起作用,但我认为这可能是朝着正确方向迈出的一步。。。错误:

Traceback (most recent call last):
  File "gnar.py", line 18, in <module>
    utsname = uts_struct(gnar)
TypeError: incompatible types, c_char_Array_512 instance instead of c_char_p instance

这是不可能的吗?在

from ctypes import *

libc = CDLL('libc.so.6')

class uts_struct(Structure):
    _fields_ = [ ('sysname', c_char_p),
                 ('nodename', c_char_p),
                 ('release', c_char_p),
                 ('version', c_char_p),
                 ('machine', c_char_p) ]

gnar = create_string_buffer(512)
libc.uname(byref(gnar))
utsname = uts_struct(gnar)

Edit3:(我要找有史以来最长的帖子。。。=P)

from ctypes import *
libc = CDLL('libc.so.6')
class uts_struct(Structure):
    _fields_ = [ ('sysname', c_char * 65),
                 ('nodename', c_char * 65),
                 ('release', c_char * 65),
                 ('version', c_char * 65),
                 ('machine', c_char * 65) ]
gnar = uts_struct()
libc.uname(byref(gnar))
print gnar.machine

但是,它在打印值后会分离错误。。。在


最终编辑:

下面的工作-我当然使用的是GNU版本的libc。(在Ubuntu机器上的im)所以添加域字段就可以停止segfault。事后看是有道理的。:)

from ctypes import *

libc = CDLL('libc.so.6')

class uts_struct(Structure):
    _fields_ = [ ('sysname', c_char * 65),
                 ('nodename', c_char * 65),
                 ('release', c_char * 65),
                 ('version', c_char * 65),
                 ('machine', c_char * 65),
                 ('domain', c_char * 65) ]

gnar = uts_struct()
libc.uname(byref(gnar))
print gnar.nodename

Tags: fromimportmachinectypesstructclasslibcuname
2条回答

根据this uname man page,该结构包含由实现定义大小的数组,而不是char*(c_char_p)。你看过sys/utsname.h中的结构定义了吗?你必须匹配精确的结构定义。数据类型可能应该是c_char * n,其中nsys/utsname.h中该字段的数组大小。在

或者,您应该能够通过使用print gnar.raw访问第一次编辑中的所有字符串,只要缓冲区对于整个结构来说足够大。在

utsname structure中的字段不是指针;它们是“未指定大小的数组”。在

因此,字符串在结构中被连续打包并以null结尾。在

我不知道如何用Python表示它。但我建议从uname()以外的东西开始做实验。:-)

[更新]

517366245708十进制为0x78756E694C,这是“xuniL”的ascii。这在64位的小端机器上是有意义的。。。在

但问题是,您使用c_char_p创建一个指针,然后在调用byref()时传递一个指向的指针。所以uname()正在填充指针(而不是它所指向的)。更糟糕的是,它在内存中放了超过8个字节,所以你当前的代码正在破坏内存。在

您需要弄清楚如何分配一个struct utsname大小的内存块,然后将一个指向的指针传递给uname()函数,然后计算出该块内部的偏移量对应于结构中的哪些字段。我不知道在Python中有多少是可能的。。。在

[第二次更新]

这样更好。。。但现在必须查看数组中的偏移量。如果这是一个典型的Linux系统,那么每个字段都是65字节(是的,真的)。所以你需要开始在字符串中读取65个字节。我不知道你能不能打电话给string.index处理这件事。。。在

相关问题 更多 >