組み込みデバイスからシステム情報を収集する方法

組み込みデバイス用のハードウェアとソフトウェアのコンポーネントの種類が増えるにつれて、ソフトウェアが実行されている動作環境を知ることがより重要になってきています。複数のプラットフォームでソフトウェアを開発する場合は、次のように、どんなプラットフォームおよびアーキテクチャが利用できるのかについて知っておく必要があります。

ソフトウェアおよびハードウェア環境の正確かつ詳細なログを残しておくことは、ソフトウェアの開発、テスト、デバッグ、および評価を円滑に進めるにあたって役立ちます。この記事では、組み込みデバイスからシステム情報を収集してログする方法をお伝えします。

f:id:PSYGIG:20190709200109j:plain

目次

  • システム情報とは
  • なぜシステム情報の収集が重要なのか
  • 無料便利ツール「psymon」とは?
  • psymonの無料ダウンロード・インストールはこちら
  • psymonでシステム情報を収集する方法
  • psymonを使用する上での詳細ガイド

システム情報とは

システム情報は、ソフトウェアが実行されているデバイスのソフトウェアおよびハードウェアコンポーネントの仕様の集合体です。システム情報の代表例は下記の通りです。 * CPU(モデル、アーキテクチャ、速度、キャッシュ、コア、パッケージ) * GPU(モデル、コア、アーキテクチャ、メモリ、速度) * メモリ(モデル、サイズ、速度、種類) * ディスク(モデル、タイプ、速度、インターフェース) * 周辺機器(インターフェイス、ベンダー、デバイス、タイプ) * ファームウェアバージョン * オペレーティングシステム(名前、バージョン、カーネルアーキテクチャ

通常、上記のような情報はコンピューティングデバイスの技術仕様としてリストされています(例:Raspberry Pi)。

なぜシステム情報の収集が重要なのか

特に組み込み開発では、コンポーネントの選択肢が無数にあるため、書いたコードがどの環境で実行されるかわかりません。同じコードでも、Raspberry PiMacBookとでは異なる実行結果になるでしょう。

ソフトウェアの問題をデバッグするという点では、正確な動作環境を知ることで、問題を単独で再現することができます。エラーが発生した環境とは異なる環境を使用している場合、追加の変数を導入することになります。システム情報のログを取っておくことで、スムーズなデバッグ作業を実施できます。

システム情報の追跡は、デバイス構築にあたってどのコンポーネントを使用するか選ぶ際の手助けにもなります。パフォーマンスメトリックとベンチマークをシステム情報データと関連付けることで、特定のタスクが特定のコンポーネントまたはプラットフォームにより適しているかどうかを客観的に評価できます。

アプリケーションを組み込みデバイスで実行するときは、psymonという軽量のツールを使用してシステム情報を収集できます。

無料便利ツール「psymon」とは?

psymonはUNIXベースのコマンドラインプログラムで、コマンドを実行する度にデバイスのシステム情報を自動で察知してファイルに記録します。たとえば、次のコマンドを実行します。

psymon [command-to-run-your-program]

psymonから始まるコマンドを実行すると、システム情報を自動でJSONまたはその他形式のファイルで記録します。

psymonの無料ダウンロード・インストールはこちら

psymonの無料最新版は下記のリンクからダウンロードできます:

https://bintray.com/psygig/releases/psyiage

詳しいインストール方法は上記リンク内の「Readme」をご覧ください。

psymonでシステム情報を収集する方法

psymonを使えば、psymonをコマンドの先頭に追加するだけで、アプリケーションのシステム情報を収集することができます。

psymon [command-to-run-your-program]

デフォルトでは、psymonはシステム情報をJSONファイルに記録します。 ただし、psymonはHTTPエンドポイント、MQTTトピック、CSVファイルなどの他の送信先およびフォーマットにログを記録するように設定できます。これにより、システム情報をリモートで追跡することが可能になります。

下記は、収集したシステム情報のサンプルJSONファイルです。

{
"SysInfo": {
"CPUInfo": {
"ThreadsPerCore": 1,
"CoresPerPackage": 1,
"NumPackages": 1,
"Vendor": "GenuineIntel",
"Model": "Intel(R) Xeon(R) CPU @ 2.30GHz",
"Architecture": "x86",
"Features": "aes avx avx2 bmi1 bmi2 cx16 erms f16c fma3 sse4_1 sse4_2 ssse3 ",
"Endian": "Little Endian",
"ClockMhz": 2300,
"X86Info": {
"Microarchitecture": "INTEL_HSW",
"Family": 6,
"Model": 63,
"Stepping": 0
},
"CacheInfo": [
{
"Level": 1,
"Size": 32768,
"LineSize": 64,
"Associativity": 8,
"Type": "Data"
},
{
"Level": 1,
"Size": 32768,
"LineSize": 64,
"Associativity": 8,
"Type": "Instruction"
},
{
"Level": 2,
"Size": 262144,
"LineSize": 64,
"Associativity": 8,
"Type": "Unified"
},
{
"Level": 3,
"Size": 47185920,
"LineSize": 64,
"Associativity": 20,
"Type": "Unified"
}
]
},
"MemInfo": {
"TotalRAM": 3874308096,
"FreeRAM": 1218797568,
"SharedRAM": 209526784,
"BufferRAM": 46354432,
"TotalSwap": 2147479552,
"FreeSwap": 2147479552,
"TotalHiMem": 0,
"FreeHiMem": 0,
"NumProcesses": 167
},
"FileSystemInfo": [
{
"Device": "/dev/sda9",
"MountDir": "/builds",
"FileSystem": "ext4",
"MountOpts": "rw,seclabel,relatime",
"BlockSize": 4096,
"FragSize": 4096,
"TotalBlocks": 5744295,
"FreeBlocks": 4309153,
"AvailBlocks": 4052546,
"TotalInodes": 5928832,
"FreeInodes": 5795366,
"AvailInodes": 5795366,
"FileSystemID": 4014506252,
"FileSystemFlags": 4096
},
{
"Device": "/dev/sda9",
"MountDir": "/etc/resolv.conf",
"FileSystem": "ext4",
"MountOpts": "rw,seclabel,relatime",
"BlockSize": 4096,
"FragSize": 4096,
"TotalBlocks": 5744295,
"FreeBlocks": 4309153,
"AvailBlocks": 4052546,
"TotalInodes": 5928832,
"FreeInodes": 5795366,
"AvailInodes": 5795366,
"FileSystemID": 4014506252,
"FileSystemFlags": 4096
},
{
"Device": "/dev/sda9",
"MountDir": "/etc/hostname",
"FileSystem": "ext4",
"MountOpts": "rw,seclabel,relatime",
"BlockSize": 4096,
"FragSize": 4096,
"TotalBlocks": 5744295,
"FreeBlocks": 4309153,
"AvailBlocks": 4052546,
"TotalInodes": 5928832,
"FreeInodes": 5795366,
"AvailInodes": 5795366,
"FileSystemID": 4014506252,
"FileSystemFlags": 4096
},
{
"Device": "/dev/sda9",
"MountDir": "/etc/hosts",
"FileSystem": "ext4",
"MountOpts": "rw,seclabel,relatime",
"BlockSize": 4096,
"FragSize": 4096,
"TotalBlocks": 5744295,
"FreeBlocks": 4309153,
"AvailBlocks": 4052546,
"TotalInodes": 5928832,
"FreeInodes": 5795366,
"AvailInodes": 5795366,
"FileSystemID": 4014506252,
"FileSystemFlags": 4096
},
{
"Device": "/dev/sda9",
"MountDir": "/sys/devices/virtual/dmi/id",
"FileSystem": "ext4",
"MountOpts": "ro,seclabel,relatime",
"BlockSize": 4096,
"FragSize": 4096,
"TotalBlocks": 5744295,
"FreeBlocks": 4309153,
"AvailBlocks": 4052546,
"TotalInodes": 5928832,
"FreeInodes": 5795366,
"AvailInodes": 5795366,
"FileSystemID": 4014506252,
"FileSystemFlags": 4097
}
],
"OSInfo": {
"Name": "Debian GNU/Linux",
"FullName": "Debian GNU/Linux 9 (stretch)",
"CodeName": "",
"Major": 9,
"Minor": 0,
"Patch": 0,
"Build": 0,
"KernelInfo": {
"Name": "Linux",
"Major": 4,
"Minor": 19,
"Patch": 23,
"Build": 0
}
},
"USBInfo": ,
"DiskInfo": [
{
"Device": "sda",
"Model": "PersistentDisk ",
"Vendor": "Google ",
"Serial": "",
"Size": 26843545600,
"PartitionInfo": [
{
"PartNum": 4,
"Start": 1212153856,
"Size": 1073741824
},
{
"PartNum": 2,
"Start": 136314880,
"Size": 2097152
},
{
"PartNum": 9,
"Start": 2487222272,
"Size": 24356306432
},
{
"PartNum": 7,
"Start": 2420113408,
"Size": 67108864
},
{
"PartNum": 3,
"Start": 138412032,
"Size": 1073741824
},
{
"PartNum": 1,
"Start": 2097152,
"Size": 134217728
},
{
"PartNum": 6,
"Start": 2285895680,
"Size": 134217728
}
]
}
],
"PCIInfo": [
{
"VendorName": "",
"DeviceName": "",
"VendorId": 6900,
"DeviceId": 4096,
"DomainNo": 0,
"BusNo": 0,
"DeviceNo": 4,
"FunctionNo": 0,
"BaseClass": 2,
"SubClass": 0,
"ProgIntfClass": 0,
"Revision": 0
},
{
"VendorName": "",
"DeviceName": "",
"VendorId": 6900,
"DeviceId": 4100,
"DomainNo": 0,
"BusNo": 0,
"DeviceNo": 3,
"FunctionNo": 0,
"BaseClass": 0,
"SubClass": 0,
"ProgIntfClass": 0,
"Revision": 0
}
],
"NetInfo": [
{
"Device": "eth0",
"MacAddr": "02:42:ac:11:00:03",
"IPAddr": "172.17.0.3",
"IP6Addr": "fe80::42:acff:fe11:3"
},
{
"Device": "lo",
"MacAddr": "",
"IPAddr": "127.0.0.1",
"IP6Addr": "::1"
}
]
},
}

psymonを使用する上での詳細ガイド

リソースの監視以外にも、psymonには下記の便利機能があります。

  • コードプロファイリング
  • クラッシュレポート
  • ログ監視
  • システム情報収集
  • アラート報告

上記で紹介した機能に加えて、psymonは組み込みアプリケーションの品質と安定性を向上するための便利機能を備えています。詳しい機能内容については、psymon公式ページ(https://bintray.com/psygig/releases/psyiage#)をご覧ください。


この記事を書いた人|キース
アイスホッケーとお笑いをこよなく愛するみんなのムードメーカー、キース。サイギグの共同創業者兼チーフエンジニア。カナダ・バンクーバー出身。カナダの名門ブリティッシュコロンビア大学卒。SonyのPlayStationのハード/ソフト開発をリードしてきた組み込みエンジニア。カナダ出身なだけあって、平日の夜はアイスホッケーを楽しむスポーツマン。一時期ブルゾンちえみにハマっていた。プライベートは謎に包まれていることが多いため、最近の生態(マイブーム)は誰も知らない。

[English Below]

Collecting system information from your embedded device

With the ever increasing number of options when it comes to choosing the hardware and software components for our embedded device, it becomes much more important for us to know the operating environment that our software is running in. If we decide to develop our software on multiple platforms, we’ll need to be aware of the variety of platforms and architectures that are available, such as:

  • Hardware platforms (Raspberry Pi, Jetson, UDOO)
  • CPU architectures (x86, arm, arm64, mips)
  • GPU (Tegra, Mali, Adreno)
  • RAM (1GB, 2GB, 4GB, LPDDR3, LPDDR4)
  • Operating systems (Windows, Linux, OpenBSD, MacOS)

Keeping detailed logs of the exact software and hardware environment will go a long way in facilitating development, testing, debugging and evaluation of our software.

What is system information, and what does it include?

System information is the collection of software and hardware component specifications of the device our software is running on. This includes but not limited to the following:

  • CPU (model, architecture, speed, cache, cores, packages)
  • GPU (model, cores, architecture, memory, speed)
  • Memory (model, size, speed, type)
  • Disk (model, type, speed, interface)
  • Peripherals (interface, vendor, device, type)
  • Firmware version
  • Operating system (name, version, kernel, architecture)

Usually you would see this information listed as the technical specifications for computing device (eg. Raspberry Pi)

Why is collecting system information important?

Especially for embedded development, where there are virtually endless number of components for us to choose from, we are likely writing some code that could run on completely different environments. Even if the code is the same, we will likely get different results on, say a Raspberry Pi than on a MacBook.

In terms of debugging software issues, knowing the exact operating environment for us allows us to reproduce the problem in isolation. Otherwise, we may be introducing additional variables if we are using a different environment than the one where the error occurred. Keeping a log of the system information will definitely help our debugging process.

Tracking the system information also helps us with some of our design decisions when choosing specific components for building our device. By associating performance metrics and benchmarks with our system information data, we can objectively evaluate whether a certain task is better suited for a specific component or platform.

We can use a lightweight tool called psymon to collect system information when running our application on an embedded device.

What is psymon?

psymon is a UNIX-based command line program that automatically detects and logs our device’s system information to a file every time we run a program on the command line. For example, we would run the following command:

psymon [command-to-run-your-program]

Running our command prefixed with psymon will automatically save the system information to a JSON file (or other formats).

Downloading and installing psymon

psymon is a free tool that you can get the latest version here:

https://bintray.com/psygig/releases/psyiage

Follow the instructions in the Readme to install.

Using psymon to collect system information

Collection system information with our application is simple, as all we need to do is prepend the command with psymon

psymon [command-to-run-your-program]

By default, psymon will record the system information to a JSON file. However, psymon can be configured to log to other destinations and formats such as HTTP endpoints, MQTT topics, CSV file, etc. This enables the possibility of tracking our system information remotely.

Here is a sample JSON file of the collected system information

{
"SysInfo": {
"CPUInfo": {
"ThreadsPerCore": 1,
"CoresPerPackage": 1,
"NumPackages": 1,
"Vendor": "GenuineIntel",
"Model": "Intel(R) Xeon(R) CPU @ 2.30GHz",
"Architecture": "x86",
"Features": "aes avx avx2 bmi1 bmi2 cx16 erms f16c fma3 sse4_1 sse4_2 ssse3 ",
"Endian": "Little Endian",
"ClockMhz": 2300,
"X86Info": {
"Microarchitecture": "INTEL_HSW",
"Family": 6,
"Model": 63,
"Stepping": 0
},
"CacheInfo": [
{
"Level": 1,
"Size": 32768,
"LineSize": 64,
"Associativity": 8,
"Type": "Data"
},
{
"Level": 1,
"Size": 32768,
"LineSize": 64,
"Associativity": 8,
"Type": "Instruction"
},
{
"Level": 2,
"Size": 262144,
"LineSize": 64,
"Associativity": 8,
"Type": "Unified"
},
{
"Level": 3,
"Size": 47185920,
"LineSize": 64,
"Associativity": 20,
"Type": "Unified"
}
]
},
"MemInfo": {
"TotalRAM": 3874308096,
"FreeRAM": 1218797568,
"SharedRAM": 209526784,
"BufferRAM": 46354432,
"TotalSwap": 2147479552,
"FreeSwap": 2147479552,
"TotalHiMem": 0,
"FreeHiMem": 0,
"NumProcesses": 167
},
"FileSystemInfo": [
{
"Device": "/dev/sda9",
"MountDir": "/builds",
"FileSystem": "ext4",
"MountOpts": "rw,seclabel,relatime",
"BlockSize": 4096,
"FragSize": 4096,
"TotalBlocks": 5744295,
"FreeBlocks": 4309153,
"AvailBlocks": 4052546,
"TotalInodes": 5928832,
"FreeInodes": 5795366,
"AvailInodes": 5795366,
"FileSystemID": 4014506252,
"FileSystemFlags": 4096
},
{
"Device": "/dev/sda9",
"MountDir": "/etc/resolv.conf",
"FileSystem": "ext4",
"MountOpts": "rw,seclabel,relatime",
"BlockSize": 4096,
"FragSize": 4096,
"TotalBlocks": 5744295,
"FreeBlocks": 4309153,
"AvailBlocks": 4052546,
"TotalInodes": 5928832,
"FreeInodes": 5795366,
"AvailInodes": 5795366,
"FileSystemID": 4014506252,
"FileSystemFlags": 4096
},
{
"Device": "/dev/sda9",
"MountDir": "/etc/hostname",
"FileSystem": "ext4",
"MountOpts": "rw,seclabel,relatime",
"BlockSize": 4096,
"FragSize": 4096,
"TotalBlocks": 5744295,
"FreeBlocks": 4309153,
"AvailBlocks": 4052546,
"TotalInodes": 5928832,
"FreeInodes": 5795366,
"AvailInodes": 5795366,
"FileSystemID": 4014506252,
"FileSystemFlags": 4096
},
{
"Device": "/dev/sda9",
"MountDir": "/etc/hosts",
"FileSystem": "ext4",
"MountOpts": "rw,seclabel,relatime",
"BlockSize": 4096,
"FragSize": 4096,
"TotalBlocks": 5744295,
"FreeBlocks": 4309153,
"AvailBlocks": 4052546,
"TotalInodes": 5928832,
"FreeInodes": 5795366,
"AvailInodes": 5795366,
"FileSystemID": 4014506252,
"FileSystemFlags": 4096
},
{
"Device": "/dev/sda9",
"MountDir": "/sys/devices/virtual/dmi/id",
"FileSystem": "ext4",
"MountOpts": "ro,seclabel,relatime",
"BlockSize": 4096,
"FragSize": 4096,
"TotalBlocks": 5744295,
"FreeBlocks": 4309153,
"AvailBlocks": 4052546,
"TotalInodes": 5928832,
"FreeInodes": 5795366,
"AvailInodes": 5795366,
"FileSystemID": 4014506252,
"FileSystemFlags": 4097
}
],
"OSInfo": {
"Name": "Debian GNU/Linux",
"FullName": "Debian GNU/Linux 9 (stretch)",
"CodeName": "",
"Major": 9,
"Minor": 0,
"Patch": 0,
"Build": 0,
"KernelInfo": {
"Name": "Linux",
"Major": 4,
"Minor": 19,
"Patch": 23,
"Build": 0
}
},
"USBInfo": ,
"DiskInfo": [
{
"Device": "sda",
"Model": "PersistentDisk ",
"Vendor": "Google ",
"Serial": "",
"Size": 26843545600,
"PartitionInfo": [
{
"PartNum": 4,
"Start": 1212153856,
"Size": 1073741824
},
{
"PartNum": 2,
"Start": 136314880,
"Size": 2097152
},
{
"PartNum": 9,
"Start": 2487222272,
"Size": 24356306432
},
{
"PartNum": 7,
"Start": 2420113408,
"Size": 67108864
},
{
"PartNum": 3,
"Start": 138412032,
"Size": 1073741824
},
{
"PartNum": 1,
"Start": 2097152,
"Size": 134217728
},
{
"PartNum": 6,
"Start": 2285895680,
"Size": 134217728
}
]
}
],
"PCIInfo": [
{
"VendorName": "",
"DeviceName": "",
"VendorId": 6900,
"DeviceId": 4096,
"DomainNo": 0,
"BusNo": 0,
"DeviceNo": 4,
"FunctionNo": 0,
"BaseClass": 2,
"SubClass": 0,
"ProgIntfClass": 0,
"Revision": 0
},
{
"VendorName": "",
"DeviceName": "",
"VendorId": 6900,
"DeviceId": 4100,
"DomainNo": 0,
"BusNo": 0,
"DeviceNo": 3,
"FunctionNo": 0,
"BaseClass": 0,
"SubClass": 0,
"ProgIntfClass": 0,
"Revision": 0
}
],
"NetInfo": [
{
"Device": "eth0",
"MacAddr": "02:42:ac:11:00:03",
"IPAddr": "172.17.0.3",
"IP6Addr": "fe80::42:acff:fe11:3"
},
{
"Device": "lo",
"MacAddr": "",
"IPAddr": "127.0.0.1",
"IP6Addr": "::1"
}
]
},
}

Advanced instrumentation using psymon

Other than resource monitoring, psymon includes other instrumentation features such as:

  • Code profiling
  • Crash reporting
  • Metrics monitoring
  • Log monitoring
  • Alert reporting

Take a look at the official psymon documentation page to see if any other the instrumentation features would be beneficial to improving the quality and robustness of your embedded applications.