Python ctypes在Linux上从libc调用reboot()

时间:2011-06-01 02:21:32

标签: python c linux ctypes libc

我试图通过reboot从Python中调用libc中的ctypes函数,但我无法让它工作。我一直在引用man 2 reboot页面(http://linux.die.net/man/2/reboot)。我的内核版本是2.6.35。

下面是来自交互式Python提示的控制台日志,我试图让我的机器重启 - 我做错了什么?

为什么ctypes.get_errno()没有工作?

>>> from ctypes import CDLL, get_errno
>>> libc = CDLL('libc.so.6')
>>> libc.reboot(0xfee1dead, 537993216, 0x1234567, 0)
-1
>>> get_errno()
0
>>> libc.reboot(0xfee1dead, 537993216, 0x1234567)
-1
>>> get_errno()
0
>>> from ctypes import c_uint32
>>> libc.reboot(c_uint32(0xfee1dead), c_uint32(672274793), c_uint32(0x1234567), c_uint32(0))
-1
>>> get_errno()
0
>>> libc.reboot(c_uint32(0xfee1dead), c_uint32(672274793), c_uint32(0x1234567))
-1
>>> get_errno()
0
>>>

修改

通过Nemos提醒 - 我可以让get_errno返回22(无效参数)。不足为奇。我该怎么称呼reboot()?我显然没有传递函数期望的参数。 =)

2 个答案:

答案 0 :(得分:3)

尝试:

>>> libc = CDLL('libc.so.6', use_errno=True)

这应该允许get_errno()工作。

[更新]

此外,最后一个参数是void *。如果这是64位系统,则整数0不是NULL的有效重复。我会尝试Nonec_void_p(None)。 (不知道在这种情况下这可能是多么重要。)

[更新2]

显然reboot(0x1234567)可以解决问题(见评论)。

答案 1 :(得分:2)

reboot()中的libc是系统调用的包装器,只接受cmd参数。所以试试:

libc.reboot(0x1234567)

请注意,您通常应该通过将SIGINT发送到PID 1来启动重新启动 - 告诉内核重新启动不会让任何系统守护程序有机会干净地关闭,甚至不会同步文件系统缓存到磁盘。