3

背景情報

ドライバーとLinuxカーネルについて学び始めたところです。write()ユーザーとその仕組みを理解したいread()。そこで、関数が進むパスを確認するためにftraceを使い始めました。しかし、次のような単一のプログラムからのトレースは「巨大」です。

int main() {
    int w;
    char buffer[] = "test string mit 512 byte";
    int fd = open("/dev/sdd",O_DIRECT | O_RDWR | O_SYNC);
    w = write(fd,buffer,sizeof(buffer));
}

また、Linuxカーネルがわからず、重要なものを捨てたくないので、どの関数をフィルタリングできるかもわかりません。

そこで、function_graphトレースの処理を開始しました。これがスニップです。

 [...]
 12)   0.468 us    |            .down_write();
 12)   0.548 us    |            .do_brk();
 12)   0.472 us    |            .up_write();
 12)   0.762 us    |            .kfree();
 12)   0.472 us    |            .fput();
 [...]

私はこれらを見.down_write().up_write()、これがまさに私が探しているものだと思いました。それで調べました。down_write()ソースコード

 /*
 * lock for writing
 */
 void __sched down_write(struct rw_semaphore *sem)
 {
       might_sleep();
       rwsem_acquire(&sem->dep_map, 0, 0, _RET_IP_);

       LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
 }

しかし、これは単にロックをロックして解放するためのものであることが判明しました。それから私は私のために小さなリファレンスを書き始めました、それで私はそれが9000以上あるように落ちるので、私はいつもこのものを調べる必要はありません。それから私はこれらの関数とそれらのコメントを解析するという考えを持っていましたトレースファイルの関数の後ろにそれらを書き込みますか?このような:

 [...]
 12)   0.468 us    |            .down_write(); lock for writing
 12)   0.548 us    |            .do_brk(); 
 12)   0.472 us    |            .up_write(); release a write lock
 12)   0.762 us    |            .kfree();
 12)   0.472 us    |            .fput();
 [...]

主な問題

それで、どうすればこれを達成できるかを考え始めました。私はそれを最も快適に感じるので、Pythonでそれをやりたいと思います。

1.問題
C関数とコメントを一致させるには、再帰一致文法を定義して実装する必要があります:(

2.問題
一部の関数は単なるラッパーであり、コメントがありません。たとえば、do_brk()折り返し__do_brk()、コメントは__do_brk()

だから、コメントの出典は他にもあるのではないかと思いました。多分ドキュメント?また、Pythonを使用したこの「ドキュメント生成」には、すでに誰かが実装されている可能性があります。

それとも、システムを理解する私の方法はread() write()非常にインテリジェントではありませんか?深く掘り下げる方法のヒントを教えていただけますか?

読んでくれてありがとう、
ファビアン

4

2 に答える 2

3

コメントの解析は実際には非常に困難です。カーネルコードの解析は特に簡単ではありません。

まず、Linuxカーネルでのシステムコールと、アプリケーションがそれらをどのように使用するかを正確に理解する必要があります。LinuxAssemblyHowToには適切な説明があります

次に、Linuxカーネルの構成を理解する必要があります。これについての良い本を読むことを強くお勧めします。

自動ツールを使用してカーネルソースコードを探索することは、多大な作業です(数日ではなく数か月)。coccinelleツール(いわゆる「セマンティックパッチ」用)を検討することもできます。プラグインを使用してGCCコンパイラをカスタマイズすることも検討できますが、MELT拡張機能を使用することもできます。

(MELTは、GCCを拡張するための高レベルのドメイン固有言語です。私はその主要な設計者および実装者です)。

GCCを使用している場合は、ミドルエンドでGCCの内部表現と処理のすべての機能を利用できます(ただし、この段階ではコメントは失われます)。

あなたがやろうとしていることは、おそらくあなたが最初に考えていたものよりもはるかに野心的です。アレクサンドル・リシーの作品も参照してください。たとえば、Linuxカーネルのモデル検査やLinuxシンポジウム2012(2012年7月)で発表する論文などです。

于 2012-06-13T12:26:54.890 に答える
0

はい、あなたのアプローチは正しいです。カーネルを学び、常にシステムコールから始めましょう。カーネルコード=通常のコードよりも高い権限で実行されるコード。Intelには約18(??わからない)の特権命令セットがあります。

http://duartes.org/gustavo/blog/post/cpu-rings-privilege-and-protection/

http://en.wikipedia.org/wiki/Privilege_level

また、ユーザーコードがこれらの特別な命令を実行するために低い特権レベルから高い特権に移行すると、標準のシステムコールメカニズムを通過します。

単純な「stracels」を実行すると、実行されている多くのシステムコールを確認できます。各システムコールは、いくつかのタスクを実行するためにカーネルに移行する必要があります。

次のような単純なスクリプトを記述します(カーネルのバージョンに依存します。特定のカーネルについては、/ sys / kernel / debug / traceing / READMEを参照してください)。

echo function > /sys/kernel/debug/tracing/current_tracer
cat /sys/kernel/debug/tracing/current_tracer

echo 1 > /sys/kernel/debug/tracing/tracing_on
ls /tmp
cat /sys/kernel/debug/tracing/trace 
echo 0 > /sys/kernel/debug/tracing/tracing_on

次の出力が得られます(ls以外のftrace出力をすべて削除した後)。

http://pastebin.com/vEk2NrDQ

上記のftrace出力は、ユーザースペースから「ls」が実行されたときに実行される実際のカーネル関数を示しています。すべての機能を理解する必要があるわけではなく、重要なわけでもありません。カーネルAPI自体を学ぶことでもありません。しかし、より重要なのは多くの概念です。異なるCPU、異なるプロセス、異なるタイプの同期プリミティブなどの間でリソースを共有する方法などです。

すべての小さな小さなステップをお楽しみください.....一度に1つずつ。

于 2014-08-02T14:00:15.730 に答える