私は大学の割り当てに低レベルのネットワークインターフェイスアクセスを持たせるためのミニモジュールに取り組んでいました(明確にするために、これは実際の割り当てではありません)。実際の割り当ては C で行われましたが、その後、ctypes を使って練習することにし、Linux と Python 2.7 をターゲットにして lib を開始しました。
Python 3.3 は、私がカバーしようとした多くの機能を公開していること、およびバージョン 2.3 前後からすでにfcntl.ioctl モジュールがあることを知っています (正確なバージョンは問題ではなく、存在するだけです)。 2.7)、このタスクは学習用でした。
私が遭遇した問題は非常に単純です。C の対応するクラスのレイアウトに基づいて、次のクラスを定義しました (明確にするために、長いスニペットを使用してください)。
class struct_ifmap(Structure):
_fields_ = [
('mem_start', c_ulong),
('mem_end', c_ulong),
('base_addr', c_ushort),
('irq', c_ubyte),
('dma', c_ubyte),
('port', c_ubyte),]
class union_ifreq_anon(Union):
_fields_ = [
('ifr_addr', struct_sockaddr),
('ifr_dstaddr', struct_sockaddr),
('ifr_broadaddr', struct_sockaddr),
('ifr_netmask', struct_sockaddr),
('ifr_hwaddr', struct_sockaddr),
('ifr_flags', c_short),
('ifr_ifindex', c_int),
('ifr_metric', c_int),
('ifr_mtu', c_int),
('ifr_map', struct_ifmap),
('ifr_slave', c_char),
('ifr_newname', c_char),
('ifr_data', c_char_p),
('raw', c_short * 15),]
class struct_ifreq(Structure):
__IFNAMSIZ = 16
_anonymous_ = [
('u'),]
_fields_ = [
('ifr_name', c_char * __IFNAMSIZ),
('u', union_ifreq_anon),]
そして、次の機能:
def _getfahwdraddr(name):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
socket.IPPROTO_IP)
ifr = struct_ifreq()
ifr.ifr_name = name
result = _libc.ioctl(sock.fileno(), 0x8927, pointer(ifr))
if result != 0:
raise OSError(get_errno())
return ''.join(['%02x:' % pair for pair in \
ifr.ifr_hwaddr.sa_data[0:6]])[:-1]
これにより得られる出力は -6c:39:-1b:XX:XX:XX であり、実際の MAC、つまり 94:39:e5:XX:XX:XX とは一致しません。1 つの手がかりは、一部の要素が正しいことかもしれませんが、ご覧のとおり、出力は単に間違っています。理由がわかりません。
驚いたことに、SO で同様の質問を見つけましたが、ほぼ同じことを目指していますが、パックされた構造と python 独自の ioctl を使用しています。それだけで機能します: Getting MAC Address . それでも、私の問題は、ctype 構造体を正しく表現して使用する方法です。