1

似乎IO#ioctl改变了通过的第二个参数。

require "socket"

SIOCGIWESSID      = 0x8B1B
IW_ESSID_MAX_SIZE = 32

sock = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
template = "a16pI2"
iwessid  = [ 'wlan0', ' ' * IW_ESSID_MAX_SIZE, IW_ESSID_MAX_SIZE, 1 ].pack(template)

iwessid_bak = iwessid.dup
p iwessid == iwessid_bak    # true

sock.ioctl(SIOCGIWESSID, iwessid)  # iwessid string changed after #ioctl

p iwessid == iwessid_bak    # false !
p iwessid, iwessid_bak      # iwessid is different, lot of zero chars \0x00
                            # appended to original content

这是预期的行为还是错误?用新的 Ruby 2.1.3 测试。

4

1 回答 1

1

这是预期的行为,否则您将如何获得您感兴趣的数据?

Ruby是围绕平台自己的系统调用IO#ioctl的一个相当薄的包装器。ioctl此系统调用(或其 C 包装器)接受整数选项和指向与该选项相关的数据结构(即结构)的指针,其中包含进出内核的数据(对于某些选项,它也可以接受整数)。因此,您设置了结构,ioctl使用指向该结构的指针作为参数进行调用,然后检查其中的更改以获取您所需要的信息。

Ruby 允许您将此结构作为 Ruby 字符串传递,但它仍需要采用系统调用所期望的格式,因此您通常需要使用pack. 之后您可能需要使用unpack相同的字符串来提取所需的数据。

我对该选项一无所知SIOCGIFHWADDR,但快速搜索会出现一个邮件列表线程,该线程似乎使用与您相同(或相似)的示例。因为代码在ioctl调用后继续:

interface, essid, len, flags = iwreq.unpack("a16pII")

虽然细节并不完全相同(unpack格式略有不同,并且它们使用了不同的变量名),但它显示了您将如何获得所需的结果。

于 2014-09-25T11:18:57.710 回答