私はしばらくの間カーネルプログラミングをいじっていて、いくつかのカスタムハードウェアでこの単純なデータ取得インターフェイスを作成したいと思っています。移植性と再利用性のために、私はRaspberryPiですべてを行います。
プロジェクトの難しい部分は、GPIOに接続された高速ADC(並列)と、ADCからのハードウェア割り込みを使用して各サンプルを取得し、chardeviceを介してアクセスできるバッファー内に保存するカーネルモジュールを持つことです。
私の現在の設定(動作する)は次のとおりです。
私は今、どれだけ速くそれを達成できるかを見たいと思っています。考慮すべき2つのことがあります。
私が「通常の」方法の上に概説したセットアップは、このようなことがどのように行われるのでしょうか?直接ファイルI/Oがカーネルからアドバイスされていないことをどこでも読んだので、私はそれをしていません。確かに、ISR中に「永続的な」場所に書き込むことは可能です。これは、割り込みを使用して一部のハードウェアからコンピューターにデータを取得しようとする一般的な問題のように思えます。
上記の設定を変更せずに、他の割り込みを無効にしてできるだけスムーズにする方法はありますか?データ収集の間、私は実際には何も必要とせず、それを止める方法のある種の方法だけが必要です。データ収集は数分間しか実行されないため、その他の割り込み(ワイヤレス、モニターの更新など)は無効にできます。その後、すべてが再開され、より要求の厳しいpythonコードを実行して、データを分析および視覚化できます(少なくともそれは私の単純な見方です)。
ユーザースペースデータ収集プログラムの場合、無限ループの何が問題になっていますか? poll
システムコールを使用している限り、効率的であるはずです: https://stackoverflow.com/questions/30035776/how-to-add-poll-function-to-the -kernel-module-code/44645336#44645336 ?
永続的なデータストレージ
それを行うための最良の方法がわかりません。投票でユーザーランドからファイルに書き込んでみませんか?届くデータが多すぎるとデータが失われるのではないかと心配していると思いますが、そうですか?
しかし、その場合の制限要因はカーネルからユーザーランドへの通信ではなく、永続ストレージデバイスの速度が遅いため、ユーザーランドでそれを行っても違いはないと思います。いずれにせよ、カーネルのみのソリューションには、次の場所で注目を集める質問があります: https://stackoverflow.com/questions/1184274/how-to-read-write-files-within-a-linux-kernel-module そして私はあなたがここでより良い解決策を得るとは思わない。
割り込みを無効にする
特にボトルネックが発生する可能性があることを考えると、それが何か違いを生むと確信していますか?お使いのデバイスが実際に多数の割り込みを生成している場合は、いずれにせよ、それらが他の割り込みを支配すると思います。他のハードウェアの状態を台無しにするリスクを冒す価値はありますか?ハードウェアデバイスの仕様は、現在のデータ帯域幅よりもはるかに広いデータ帯域幅を物理的に提供できることを示唆していますか?
自分でそれを行う方法はわかりませんが、答えが必要な場合は、「Linuxカーネルモジュールからのすべての割り込みを無効にする方法」というタイトルの別の質問をするのが最善の策です。 LDD2はcli()
関数について言及しています http://www.xml.com/ldd/chapter/book/ch09.html しかし、非推奨のようです: https ://notes.shichao.io/lkd/ch7/#no-more-global-cli そのテキストは、_local_irq_disable
_と_local_irq_save
_を示唆しています。
また、割り込みを無効にするために見つけた方法でハックして、Niceメソッドが存在するかどうかをさらに調べる前に、効率が上がるかどうかを確認します。
エミュレーターでは、簡単に:
_static int myinit(void)
{
pr_info("hello init\n");
unsigned long flags;
local_irq_save(flags);
return 0;
}
_
失敗する:
_returned with disabled interrupts
_
どうやらv4.16 _do_one_initcall
_から来ているので、そのための特別なエラー処理があります!
次に、ワーカースレッドから素朴にそれを実行してみました。
_static int work_func(void *data)
{
unsigned long flags;
local_irq_save(flags);
return 0;
}
static int myinit(void)
{
kthread = kthread_create(work_func, NULL, "mykthread");
wake_up_process(kthread);
return 0;
}
_
しかし、それでも効果を観察できないため、次のことから推測できるように、割り込みは他の何かによって有効にされている必要があります。
_watch -n 1 grep i8042 /proc/interrupts
_
ttyまたはmuse /キーボード割り込みを更新し続けます。
Fopsなどの他のエントリポイントから、または生のasm("cli")
を試した場合も同じです。もっと知識のあるアプローチが必要になります。