【问题标题】:ctypes for mmapping and copying data用于映射和复制数据的 ctypes
【发布时间】:2020-02-06 22:06:10
【问题描述】:

我的目标很简单。我想使用 mmap 分配一个内存页,然后将 hello world 字符串复制到该内存页中。

但是我在libc.memcpy(pageLoc, temp, ctypes.c_int(len(temp.value))) 行遇到了分段错误

由于我还是 ctypes 的新手,我怀疑这与我滥用指针有关。谁能告诉我为什么会这样,我做错了什么?

import ctypes

# initialize the ctype library
libc = ctypes.CDLL("libc.so.6")
pthread = ctypes.CDLL("libpthread.so.0")

# size of pages on system
PAGESIZE = ctypes.c_int(libc.getpagesize())

# allocate the page
pageLoc = ctypes.c_void_p(libc.mmap(0, PAGESIZE, 0x7, 0x22, 0, 0)) # defined in https://sites.uclouvain.be/SystInfo/usr/include/bits/mman.h.html
print "[*] Created a page in memory at address %s" % hex(pageLoc.value)

# copy hello world into the memory space
temp = ctypes.c_char_p("Hello world!\n\x00")
print hex(ctypes.c_void_p(
    libc.memcpy(pageLoc, temp, ctypes.c_int(len(temp.value)))
))

# free the page
libc.munmap(pageLoc, PAGESIZE)

【问题讨论】:

    标签: python linux python-2.7 ctypes


    【解决方案1】:

    ctypes 默认假定所有函数都返回int,这意味着在 64 位机器上,返回的指针将被截断为 32 位,从而破坏它。

    为了安全起见,您应该为您调用的每个 libc 函数指定参数和结果类型,如下所示:

    from ctypes import *
    libc.getpagesize.argtypes = []
    libc.getpagesize.restype = c_int
    libc.mmap.argtypes = [c_void_p, c_size_t, c_int, c_int, c_int, c_long]
    libc.mmap.restype = c_void_p
    libc.memcpy.argtypes = [c_void_p, c_void_p, c_size_t]
    libc.memcpy.restype = c_void_p
    libc.munmap.argtypes = [c_void_p, c_size_t]
    libc.munmap.restype = c_int
    

    有了这些类型定义,您的代码就可以正常工作。此外,它会正确地对所有参数进行类型检查并为您转换返回类型,因此您可以移除 libc 函数调用周围的转换。

    【讨论】:

    • 很好的答案,但值得一提的是ctypes 将其基本类型转换为python 类型。即使在libc.mmap.restype = c_void_p 之后,此调用的返回值也是python int,而不是c_void_p 对象。 int 可以在后面的clib.mmap 调用中使用,因为它的argtypes 也被声明了。这在打印值时可能会造成混淆。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-03
    • 1970-01-01
    • 1970-01-01
    • 2021-01-09
    相关资源
    最近更新 更多