概要
コードリーディングの勉強も兼ねて、dmidecodeコマンドの実装をかなりざっくりと概要だけ追った時のメモです。使用した環境の構築メモは下記に記載しています。
誤りや過不足があればご指摘いただければ幸いです。
環境
- CentOS 6.9
- dmidecode-2.12
dmidecodeコマンド
DMI(いわゆるSMBIOS)テーブルからハードウェア情報をダンプするコマンドです。サーバ情報や物理CPU数などを確認する際に使用することが多いです。詳細はdmidecode(8)のmanページをご参照ください。
dmidecodeコマンドの実装をざっくりと
-
mmap(2)
で/dev/mem
をメモリマッピングしていました。これは、dmidecodeコマンドで使用するハードウェア情報はSMBIOSに格納されているのですが、Linuxでは/dev/mem
からSMBIOSを読み取れるためだそうです。
util.c
127 mmp = mmap(0, mmoffset + len, PROT_READ, MAP_SHARED, fd, base - mmoffset);
- なので、
/dev/mem
が存在しないDockerコンテナなどでdmidecodeコマンドを実行すると下記のようにエラーとなります。
# dmidecode 2.12
/dev/mem: No such file or directory
-
/dev/mem
のオフセットが0xF0000
から0xFFFFF
までを順に読んでいき、_SM_
という文字列が現れたら、そこを起点として読み取った内容をダンプする実装でした。なお、_DMI_
という文字列が現れたら、SMBIOSとは異なるレガシーな方法でダンプします。
dmidecode.c
4672 if ((buf = mem_chunk(0xF0000, 0x10000, opt.devmem)) == NULL)
4673 {
4674 ret = 1;
4675 goto exit_free;
4676 }
4677
4678 for (fp = 0; fp <= 0xFFF0; fp += 16)
4679 {
4680 if (memcmp(buf + fp, "_SM_", 4) == 0 && fp <= 0xFFE0)
4681 {
4682 if (smbios_decode(buf+fp, opt.devmem))
4683 {
4684 found++;
4685 fp += 16;
4686 }
4687 }
4688 else if (memcmp(buf + fp, "_DMI_", 5) == 0)
4689 {
4690 if (legacy_decode(buf + fp, opt.devmem))
4691 found++;
4692 }
4693 }
- VirtualBoxの仮想環境で
/dev/mem
をhexdumpコマンドで16進ダンプして見たところ、特定のオフセット間に確かに_SM_
が存在することが見て取れます。
hexdump
# hexdump -C /dev/mem | grep _SM_
000fff60 5f 53 4d 5f 7d 1f 02 05 ff 00 00 00 00 00 00 00 |_SM_}...........|
- 上記実装について、System Management BIOS 等に纏まっていたことを後々確認しました(汗)