チュートリアル
Linuxでオーバーヘッドが削減できるsyscallを使ったドライバ
課題
・Linuxシステムで、さらにオーバーヘッドを削減したい。
・テストポイントを挿入しているアプリが、ファイルアクセス権限によって、procファイルへアクセスできないシステムで使いたい。
解決方法
syscallを使ったドライバを使用します。
従来のサンプルドライバは、構造体を使ってユーザー領域からカーネル領域へデータを渡していましたが、
その処理が不要になる分、オーバーヘッド削減が可能となります。
また、従来の方法では、procフォルダの権限を変えるか、アプリ起動時にroot権限での起動が必要でしたが、
syscallの方法ではアクセス権限に関係なく使用できるようになります。
効果
弊社で提供する従来のサンプルドライバを(Procファイルシステム)ご使用いただいた場合よりも、
オーバーヘッドを削減することができます。
従来のサンプルドライバ : 約 3.2us
syscallを使ったドライバ : 約 1.7us
ドライバのカスタム方法
syscallを使用する形でDT10を環境に組み込む際の作業手順と使い方を説明します。
接続方式は、ファイル書き出しです。
Linuxディストリビューションやバージョンなどによって、若干異なるケースがございます。
また、archフォルダ以下についてはターゲットのCPUにてフォルダが分かれますので、
使用しているCPUに合わせて組み込むようにご注意ください。
ここではx86系を例として説明します。
1. サンプルドライバのダウンロード
対応OS | 接続方式 | 言語 | イベントID出力方式 | ダウンロード | 備考 |
---|---|---|---|---|---|
Linux | ファイル書き出し (18Byte) |
C/C++ | カーネル情報出力 ポイント挿入 |
ダウンロード | DT10Ver11.00以降のサンプルドライバ |
Linux | ファイル書き出し (18Byte) |
C/C++ | カーネル情報出力 ポイント挿入 |
ダウンロード | DT10Ver10.51以前のサンプルドライバ |
2. syscallフォルダの構成
使用する定義を下記のように変更します。
syscall
├app … dt10appを作製
│├ProcFileOutput.c … dt10app の実体
│└Makefile
│
├kernel…Kernel向け
││階層は[Linux]相当
│├arch
││└x86
││ ├include
││ │ └asm
││ │ ├unistd_32.h … syscall番号の登録(32bit)
││ │ └unistd_64.h … syscall番号の登録(64bit)
││ │
││ └kernel
││ └syscall_table_32.S … syscallTabel登録(32bit)
││
│├include
││ ├asm-x86
││ │ └asm-offsets.h … syscall最大値の設定(64bit)
││ │
││ └linux
││ └syscalls.h … syscallの宣言一覧(共通)
│└drivers
│ └misc
│ └dt_datawriting_drv.c … DT10カーネルモジュール
│ MakefileはmiscのMakefileに追加
│
└userspace
└dt10_tpdrv.c … ユーザーランド向けドライバ
appフォルダ、及び userspaceフォルダ以下のファイルは、ユーザーランド層に対応しています。
kernelフォルダ以下のファイルは、カーネル層に対応しています。
kernelフォルダについては、Linuxのフォルダ構成に従った階層になっていますので、
構成を変更せずに、そのままの位置で設置します。
3. DT10用システムコールの登録
DT10の処理をシステムコールで処理できるように、カーネル側に設定します。
なお、32bit環境と64bit環境によって、操作するファイルが異なりますのでご注意ください。
■32bit環境の場合
(1) linux/arch/x86/include/asm/unistd_32.h の変更
システムコールのdefineにDT10のシステムコールを追加します。
unistd_32.h の最後に以下の2つを追加します。
#define __NR_dt10_write 337
#define __NR_dt10_writev 338
“NR_syscalls”がシステムコールの最大値になりますので追加分を更新します。
#define NR_syscalls 340
(2) linux/arch/x86/kerne/syscall_table_32.S の変更
以下の設定を最後に追加します。
.long sys_dt10_write
.long sys_dt10_writev
(3) linux/include/linux/syscalls.hの変更
syscall.h の最終行に以下の2つの宣言を追加します。
asmlinkage long sys_dt10_write(unsigned int addr, unsigned int dat);
asmlinkage long sys_dt10_writev
(unsigned int addr, unsigned int dat, void __user *p, unsigned int size);
■64bit環境の場合
(1) linux/arch/x86/include/asm/unistd_64.h の変更
システムコールのdefineにDT10のシステムコールを追加します。
(2) __NR_syscall_max の変更
システムコールの最大値を修正します。
Linuxのバージョンによって差異がありますので、以下のような形で検索し、
“__NR_syscall_max”の値を手順(1)で変更した値に修正します。
find ~/ linux -type f -name "*.h" | xargs grep "__NR_syscall_max"
grep -r "__NR_syscall_max"
以下に、参考例を記載します。
linux/include/asm-x86/asm-offsets.hへ移動
上記の赤枠の箇所のように修正してください。
その他、別のLinuxバージョンでは、下記のように、別ファイルにて定義されており
unistd.hの変更のみで対応されている場合もあります。
linux/arch/x86/kernel/asm_offsets_64.c
(3) linux/include/linux/syscalls.hの変更
syscall.h の最終行に以下の2つの宣言を追加します。
asmlinkage long sys_dt10_write(unsigned int addr, unsigned int dat);
asmlinkage long sys_dt10_writev
(unsigned int addr, unsigned int dat, void __user *p, unsigned int size);
4. dt_datawriting_drv.c の登録
linux/drivers/misc直下にdt_datawriting_drv.cを登録します。
サンプルコードの修正は特に必要ありません。
miscのMakefileに dt_datawriting_drv.c を登録します。
5. userspace/dt10_tpdrv.c の登録
DT10のテストポイントを挿入したアプリのMakefileにdt10_tpdrv.cを追加します。
「3. DT10用システムコールの登録」で変更した際のunistd_32/64.hの値に変更してください。
6. app から dt10appの設定
サンプルドライバ内のMakefileからMakeを実行する事で、dt10app が作成されます。
ソースファイルの実体は、同ファイル内のProcFileOutput.cとなっています。
Makeする前に、以下の点を修正してください。
proc上に保存されているログデータの保存先を指定します。
#define CONVERT_FILE を変更します。
変更が完了したら、Makeコマンドを実行しdt10appを生成します。
7. 動作確認
Procを操作する為、dt10app は root権限で操作する必要があります。
こちらは操作の例です。Convertdata.DATが生成されることを確認してください。