Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 来自ctypes的垃圾uint64值_Python_Macos_Ctypes_Bsd - Fatal编程技术网

Python 来自ctypes的垃圾uint64值

Python 来自ctypes的垃圾uint64值,python,macos,ctypes,bsd,Python,Macos,Ctypes,Bsd,我正在尝试从结构if_data64中读取字段ifi_ibytes/ifi_obytes,如中所述。我已经让ctypes工作了,我可以进行sysctl调用,我从中得到了似乎有用的信息。然而,我从非零整数中得到的似乎是总垃圾。例如,我有一个接口,接收0字节,传输850万字节。然而,我的python代码表示接收到0,发送3590592659456字节 我复制了Python中的方法,从Python中获得的字节数与上面所示的MenuMeter数没有任何相似之处。我使用的是一个稍有不同的sysctl(NET

我正在尝试从结构if_data64中读取字段ifi_ibytes/ifi_obytes,如中所述。我已经让ctypes工作了,我可以进行sysctl调用,我从中得到了似乎有用的信息。然而,我从非零整数中得到的似乎是总垃圾。例如,我有一个接口,接收0字节,传输850万字节。然而,我的python代码表示接收到0,发送3590592659456字节

我复制了Python中的方法,从Python中获得的字节数与上面所示的MenuMeter数没有任何相似之处。我使用的是一个稍有不同的sysctl(NET_RT_IFLIST2),它给出了我在代码中考虑的64位整数

这是我的密码:

from ctypes import *
from ctypes.util import find_library
from ctypes import sizeof as c_sizeof
import errno

libc = CDLL(find_library('c'), use_errno=True)

# hardcoded macosx constants!
CTL_NET = 4
PF_ROUTE = 17
NET_RT_IFLIST2 = 6

RTM_IFINFO2 = 0x12
IFF_LOOPBACK = 0x8
AF_LINK = 18

class if_data64(Structure):
   _pack_ = 4
   _fields_ = [('ifi_type', c_ubyte),
               ('ifi_typelen', c_ubyte),
               ('ifi_physical', c_ubyte),
               ('ifi_addrlen', c_ubyte),
               ('ifi_hdrlen', c_ubyte),
               ('ifi_recvquota', c_ubyte),
               ('ifi_xmitquota', c_ubyte),
               ('ifi_unused1', c_ubyte),
               ('ifi_mtu', c_uint32),
               ('ifi_metric', c_uint32),
               ('ifi_baudrate', c_uint32),
               ('ifi_ipackets', c_uint64),
               ('ifi_ierrors', c_uint64),
               ('ifi_opackets', c_uint64),
               ('ifi_oerrors', c_uint64),
               ('ifi_collisions', c_uint64),
               ('ifi_ibytes', c_uint64),
               ('ifi_obytes', c_uint64),
               ('ifi_imcasts', c_uint64),
               ('ifi_omcasts', c_uint64),
               ('ifi_iqdrops', c_uint64),
               ('ifi_noproto', c_uint64),
               ('ifi_recvtiming', c_uint32),
               ('ifi_xmittiming', c_uint32)]

class if_msghdr2(Structure):
   _fields_ = [('ifm_msglen', c_ushort),
               ('ifm_version', c_ubyte),
               ('ifm_type', c_ubyte),
               ('ifm_addrs', c_int),
               ('ifm_flags', c_int),
               ('ifm_index', c_ushort),
               ('ifm_snd_len', c_int),
               ('ifm_snd_maxlen', c_int),
               ('ifm_snd_drops', c_int),
               ('ifm_timer', c_int),
               ('ifm_data', if_data64)]

class sockaddr_dl(Structure):
   _fields_ = [('sdl_len', c_ubyte),
               ('sdl_family', c_ubyte),
               ('sdl_index', c_ushort),
               ('sdl_type', c_ubyte),
               ('sdl_nlen', c_ubyte),
               ('sdl_alen', c_ubyte),
               ('sdl_slen', c_ubyte),
               ('sdl_data', c_char * 12)] # for now

MIB_TYPE = c_int * 6
mib = MIB_TYPE(CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0)

sysctl_buf_len = c_uint(0)

rval = libc.sysctl(mib, 6, None, byref(sysctl_buf_len), None, 0)
if rval != 0:
   raise Exception(errno.errorcode[get_errno()])

sysctl_buf = create_string_buffer(sysctl_buf_len.value)
rval = libc.sysctl(mib, 6, sysctl_buf, byref(sysctl_buf_len), None, 0)
if rval != 0:
   raise Exception(errno.errorcode[get_errno()])

# walk the structure.  you need to know the length from ifm_msglen
idx = addressof(sysctl_buf)
end = idx + sysctl_buf_len.value
while idx < end:
   batch_off = idx - addressof(sysctl_buf)
   ifmsg = cast(c_void_p(idx), POINTER(if_msghdr2))
   if ifmsg.contents.ifm_type != RTM_IFINFO2:
      idx += ifmsg.contents.ifm_msglen
      continue
   if ifmsg.contents.ifm_flags & IFF_LOOPBACK:
      idx += ifmsg.contents.ifm_msglen
      continue
   # 12 bytes to compensate for 32 bit alignment
   sdl = cast(c_void_p(idx + c_sizeof(if_msghdr2) + 12), POINTER(sockaddr_dl))
   if sdl.contents.sdl_family != AF_LINK:
      idx += ifmsg.contents.ifm_msglen
      continue

   print sdl.contents.sdl_data[0:sdl.contents.sdl_nlen]
   print ifmsg.contents.ifm_data.ifi_ibytes, ifmsg.contents.ifm_data.ifi_obytes
   idx += ifmsg.contents.ifm_msglen
从ctypes导入*
从ctypes.util导入查找库
从ctypes导入sizeof作为c_sizeof
输入错误号
libc=CDLL(查找库('c'),使用errno=True)
#硬编码macosx常量!
CTL_净=4
PF_路线=17
净流量2=6
RTM_IFINFO2=0x12
IFF_环回=0x8
AF_链路=18
类如果_data64(结构):
_包装=4
_字段\=[('ifi_类型',c_字节),
('ifi_typelen',c_ubyte),
('ifi_physical',c_ubyte),
(“ifi_addrlen”,c_ubyte),
('ifi_hdrlen',c_ubyte),
('ifi_recvquota',c_ubyte),
('ifi_xmitquota',c_ubyte),
('ifi_unused1',c_ubyte),
('ifi_mtu',c_uint32),
('ifi_metric',c_uint32),
('ifi_baudrate',c_uint32),
('ifi_iPackes',c_uint64),
(“ifi_ierrors”,c_uint64),
(“ifi_opackes”,c_uint64),
('ifi_oerrors',c_uint64),
(“ifi_碰撞”,c_uint64),
(“ifi_ibytes”,c_uint64),
('ifi_obytes',c_uint64),
('ifi_imcasts',c_uint64),
('ifi_omcasts',c_uint64),
('ifi_iqdrops',c_uint64),
('ifi_noproto',c_uint64),
('ifi_recvtiming',c_uint32),
('ifi_xmitting',c_uint32)]
类如图msghdr2(结构):
_字段=[('ifm_msglen',c_ushort),
('ifm_version',c_ubyte),
('ifm_type',c_ubyte),
('ifm_addrs',c_int),
('ifm_flags',c_int),
('ifm_index',c_ushort),
('ifm_snd_len',c_int),
('ifm_snd_maxlen',c_int),
('ifm_snd_drops',c_int),
('ifm_timer',c_int),
('ifm_data',if_data64)]
sockaddr_dl类(结构):
_字段=[('sdl_len',c_ubyte),
('sdl_family',c_ubyte),
(‘sdl_索引’、c_-ushort),
(“sdl_类型”,c_ubyte),
('sdl_nlen',c_ubyte),
('sdl_alen',c_ubyte),
('sdl_slen',c_ubyte),
('sdl_data',c_char*12)]#目前
MIB_TYPE=c_int*6
mib=mib_类型(CTL_网络、PF_路由、0、0、网络RT_IFLIST2、0)
sysctl_buf_len=c_uint(0)
rval=libc.sysctl(mib,6,None,byref(sysctl_buf_len),None,0)
如果rval!=0:
引发异常(errno.errorcode[get\u errno()]))
sysctl\u buf=创建字符串缓冲区(sysctl\u buf\u len.value)
rval=libc.sysctl(mib,6,sysctl_buf,byref(sysctl_buf_len),None,0)
如果rval!=0:
引发异常(errno.errorcode[get\u errno()]))
#沿着建筑物走。你需要知道ifm_msglen的长度
idx=地址(sysctl\u buf)
end=idx+sysctl\u buf\u len.value
而idx
中,如果数据64
,则
ifi\u波特率
字段应为
c\u uint64
,而不是
c\u uint32
。修复此问题应将
ifi_字节
ifo_字节
对齐到正确的偏移量。它还缺少最后一个字段,
ifi\u lastchange
。这是一个8字节的
timeval32
结构。总之,这解释了为什么
sdl
需要额外的12字节偏移量

class timeval32(Structure):
    _fields_ = [('tv_sec', c_int32), 
                ('tv_usec', c_int32)]

class if_data64(Structure):
    _pack_ = 4
    _fields_ = [('ifi_type', c_ubyte),
                ('ifi_typelen', c_ubyte),
                ('ifi_physical', c_ubyte),
                ('ifi_addrlen', c_ubyte),
                ('ifi_hdrlen', c_ubyte),
                ('ifi_recvquota', c_ubyte),
                ('ifi_xmitquota', c_ubyte),
                ('ifi_unused1', c_ubyte),
                ('ifi_mtu', c_uint32),
                ('ifi_metric', c_uint32),
                ('ifi_baudrate', c_uint64),    # was c_uint32
                ('ifi_ipackets', c_uint64),
                ('ifi_ierrors', c_uint64),
                ('ifi_opackets', c_uint64),
                ('ifi_oerrors', c_uint64),
                ('ifi_collisions', c_uint64),
                ('ifi_ibytes', c_uint64),
                ('ifi_obytes', c_uint64),
                ('ifi_imcasts', c_uint64),
                ('ifi_omcasts', c_uint64),
                ('ifi_iqdrops', c_uint64),
                ('ifi_noproto', c_uint64),
                ('ifi_recvtiming', c_uint32),
                ('ifi_xmittiming', c_uint32),
                ('ifi_lastchange', timeval32)] # was missing
我不使用带指针的
cast
,而是使用
from_buffer
方法(Python 2.6+)和偏移量编写循环

buf_offset = 0
while buf_offset < sysctl_buf_len.value:
   msg_offset = buf_offset
   ifmsg = if_msghdr2.from_buffer(sysctl_buf, msg_offset)
   buf_offset += ifmsg.ifm_msglen
   if ifmsg.ifm_type != RTM_IFINFO2 or ifmsg.ifm_flags & IFF_LOOPBACK:
      continue
   sdl_offset = msg_offset + c_sizeof(if_msghdr2)
   sdl = sockaddr_dl.from_buffer(sysctl_buf, sdl_offset)
   if sdl.sdl_family != AF_LINK:
      continue
   print sdl.sdl_data[:sdl.sdl_nlen]
   print ifmsg.ifm_data.ifi_ibytes, ifmsg.ifm_data.ifi_obytes
buf_offset=0
当buf_offset
注意,十进制的3590592659456是十六进制的34400000000。也许它应该是344十六进制(836字节传输,十进制)。原因可能是将包含int32的内存称为int64,反之亦然。我不知道如何在CType中执行指针算法,就像您在参考实现的第110行中看到的那样,所以我手动填充它。我确实需要一些偏移来进行对齐,因为sockaddr_dl结构在if_msghdr2之后确实存在12个字节(正如sdl_nlen/sdl_数据字段正确所确认的那样)。