加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – 指向IOCTL调用缓冲区的指针

发布时间:2020-12-17 02:13:51 所属栏目:百科 来源:网络整理
导读:我正在使用 Ruby和bit-struct在测试设置中配置我的网络接口.这适用于大多数IOCTL调用,但我无法弄清楚如何调用SIOCGIFCONF 这是一个例子: 如果我想获取接口的MAC地址,我会写这样的东西: class LinuxIfreqMacAddr BitStruct char :name,128 unsigned :type,1
我正在使用 Ruby和bit-struct在测试设置中配置我的网络接口.这适用于大多数IOCTL调用,但我无法弄清楚如何调用SIOCGIFCONF

这是一个例子:

如果我想获取接口的MAC地址,我会写这样的东西:

class LinuxIfreqMacAddr < BitStruct
  char       :name,128
  unsigned   :type,16,:endian => :native
  hex_octets :macaddr,48
  pad        :padding,64
end

ifr = LinuxIfreqMacAddr.new
ifr.name = "eth0"
s.ioctl(SIOCGIFHWADDR,ifr) # s is a socket
puts ifr.macaddr

这很好,并将打印eth0的MAC地址.但是“struct ifconf”(与SIOCGIFCONF一起使用)的签名需要传递缓冲区.

这是签名:

struct ifconf  {
    int     ifc_len;
    char __user *ifcu_buf;
};

我如何从ruby调用SIOCGIFCONF ioctl命令,缓冲区为4096字节?

解决方法

使用 Array#pack的“P”说明符存储指向a的指针
缓冲:

require 'socket'
sock = UDPSocket.new
ifreqs = ' ' * 4096
ifconf = [ifreqs.size,ifreqs].pack("l!P")
SIOCGIFCONF = 0x8912
sock.ioctl(SIOCGIFCONF,ifconf)
data_size = ifconf.unpack('l!').first
p data_size # => 120

这是如何工作的

创建ioctl将存储接口信息数组的缓冲区:

ifreqs = ' ' * 4096

现在创建缓冲区以传递给ioctl调用.缓冲区将是一个
表示ifconf struct的字符串:

struct ifconf {
    int                 ifc_len; /* size of buffer */
    union {
        char           *ifc_buf; /* buffer address */
        struct ifreq   *ifc_req; /* array of structures */
    };
};

我们使用Array#pack来做到这一点:

ifconf = [ifreqs.size,ifreqs].pack("l!P")

格式说明符分解为:

>“我!” – 签名长的平台原生大小.这编码ifreqs.size.
>“P” – 指向固定长度缓冲区的指针.这编码地址
存储在ifreqs字符串中的缓冲区.

现在我们可以打电话:

SIOCGIFCONF = 0x8912
sock.ioctl(SIOCGIFCONF,ifconf)

SIOCGIFCONF调用修改ifconf缓冲区,将ifc_len更新为
实际存储在ifreqs bufffer中的数据字节数.我们
通过解压缩数组中的元素可以看到:

data_size = ifconf.unpack('l!').first
p data_size # => 120

将存储在ifreqs中的数据解码为一个练习读者.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读