質問: linuxカーネル:初心者向けチュートリアル 個人的な楽しみのために、カーネルの内部の変更、パッチの適用、デバイスドライバーとモジュールの処理に興味があります。経験豊富なプログラマ向けのカーネルハッキングに関する包括的なリソースはありますか?
回答: **todo** +editpic: linux kernel developer -> (ring layer 0) +addsection: kernel virtualization engine kern_warn_coding_style: do not loop unless you absolutely have to. 未初期化void *iの推奨書籍 「ある程度の寿命があるまで、または少なくともいずれかの人がその内容の少なくとも一部を見て生活するまで、誰も深い本を理解しないまで、本を理解しません」。 –エズラポンド 千コードマイルの旅は、単一のステップで開始する必要があります。次のどの本から始めるかについて混乱している場合は、心配しないで、好きなものを1つ選んでください。さまよっているすべての人が失われるわけではありません。 すべての道路が最終的にhighwayに接続するので、ページが行き止まりにぶつかることなくページが進むにつれて、カーネルの旅の新しいものを探索し、最終的にcode-setに接続します。注意して読んで覚えてください:コードは文学ではありません。残されたものは、モノや感情、イメージ、心の絵、記憶、アイデアではありません。機能です。ある種のプロセス。 「より大きな」ものの関数として説明できる人生の側面。したがって、それは他の何かから実際には「分離」されていないように見えます。ナイフの機能のように、何かを切ることは、実際には、ナイフ自体から切り離されていません。この関数は現時点で使用されている場合と使用されていない場合がありますが、決して分離することはありません。 素数性テスト用のsolovay strassenランダム化アルゴリズム :矛盾しないように読んでください。信じて当然のことと考えてはいけません。話や談話を見つけることも、しかし、検討して検討します。味わう本、飲み込む本、噛んで消化する本の一部:つまり、一部しか読んでいない本、読んでいるが不思議ではない本、完全に読んでいる本、そして勤勉さと注意をもって。static void tasklet_hi_action(struct softirq_action *a) { struct tasklet_struct *list; local_irq_disable(); list = __this_cpu_read(tasklet_hi_vec.head); __this_cpu_write(tasklet_hi_vec.head, null); __this_cpu_write(tasklet_hi_vec.tail, this_cpu_ptr(&tasklet_hi_vec.head)); local_irq_enable(); while (list) { struct tasklet_struct *t = list; list = list->next; if (tasklet_trylock(t)) { if (!atomic_read(&t->count)) { if (!test_and_clear_bit(tasklet_state_sched, &t->state)) bug(); t->func(t->data); tasklet_unlock(t); continue; } tasklet_unlock(t); } local_irq_disable(); t->next = null; *__this_cpu_read(tasklet_hi_vec.tail) = t; __this_cpu_write(tasklet_hi_vec.tail, &(t->next)); __raise_softirq_irqoff(hi_softirq); local_irq_enable(); } } コアlinux(5-> 1-> 3-> 2-> 7-> 4-> 6) 「自然にはカーネルもシェルもありません。彼女は一度にすべてです。」-johann wolfgang von goethe 読者は オペレーティングシステムの概念 に精通している必要があります。実行時間の長いプロセスと、実行のバーストが短いプロセスとの違いの公正な理解。ソフトとハードのリアルタイム制約を満たしながら、フォールトトレランス。読んでいる間、コアサブシステムのlinuxカーネルソースによって行われた設計の選択を理解し、n/ackすることが重要です。スレッド[および]シグナルは、プラットフォームに依存した、悲惨さ、絶望、恐怖、および狂気(〜anthony baxte)の軌跡です。とはいえ、カーネルに飛び込む前に、自己評価型のcエキスパートになる必要があります。また、リンクリスト、スタック、キュー、red blacksツリー、ハッシュ関数などについても優れた経験が必要です。volatile int i; int main(void) { int c; for (i=0; i<3; i++) { c = i&&&i; printf("%d\n", c); /* find c */ } return 0; } linuxカーネルソースの美しさと芸術は、一緒に使用される意図的なコードの難読化にあります。これは、クリーンでエレガントな方法で2つ以上の操作を含む計算上の意味を伝えるために必要になることがよくあります。これは、マルチコアアーキテクチャ用のコードを記述するときに特に当てはまります。 ビデオ講義リアルタイムシステム 、 タスクスケジューリング 、 メモリ圧縮 、 メモリバリア 、 [〜#〜] smp [〜#〜] #ifdef __compiler_offsetof #define offsetof(type,member) __compiler_offsetof(type,member) #else #define offsetof(type, member) ((size_t) &((type *)0)->member) #endif linuxカーネル開発 -robert love linuxカーネルの理解 -daniel p. bovet、marco cesati the linux of kernel design -yang lixiang professional linux kernel architecture -wolfgang mauerer nixオペレーティングシステムの設計 -モーリスj.バッハ linux virtual memory managerについて -mel gorman linuxカーネル内部 -tigran aivazian embedded linux primer -クリストファーハリナン linuxデバイスドライバー(1-> 2-> 4-> 3-> 8-> ...) 「音楽はあなたを運ばない。感情や物語の小さな小さな核に本当に集中するあなたの能力によって、あなたは厳密にそれを運ばなければならない」。 -デビーハリー あなたの仕事は基本的にハードウェアデバイスとソフトウェアカーネルの間の高速通信インターフェースを確立することです。ハードウェアリファレンスデータシート/マニュアルを読んで、デバイスの動作、デバイスの制御とデータの状態、および提供されている物理チャネルを理解する必要があります。特定のアーキテクチャのアセンブリに関する知識と、vhdlやverilogなどのvlsiハードウェア記述言語に関する公正な知識があれば、長期的に役立ちます。 インテル®64およびia-32アーキテクチャーソフトウェア開発者向けマニュアル armアーキテクチャリファレンスマニュアル armシステム開発者ガイド [〜#〜] q [〜#〜]:しかし、なぜハードウェアの仕様を読まなければならないのですか?[〜#〜] a [〜#〜]:なぜなら、「ソフトウェアがブリッジできないカーボンとシリコンの裂け目がある」-rahulソナドただし、上記はcomputational algorithms( driver code - bottom-half処理 ) niversal turing machine で完全にシミュレーションできるため。計算結果が 数学的ドメイン で真である場合、それが 物理ドメイン でも真であることは確実です。 linuxデバイスドライバーのビデオ講義 (lec。17&18)、 組み込みkmsドライバーの構造 、 ピン制御とgpio更新 、 共通クロックフレームワーク 、 実際のlinuxドライバーを作成する-greg kh static irqreturn_t phy_interrupt(int irq, void *phy_dat) { struct phy_device *phydev = phy_dat; if (phy_halted == phydev->state) return irq_none; /* it can't be ours. */ /* the mdio bus is not allowed to be written in interrupt * context, so we need to disable the irq here. a work * queue will write the phy to disable and clear the * interrupt, and then reenable the irq line. */ disable_irq_nosync(irq); atomic_inc(&phydev->irq_disable); queue_work(system_power_efficient_wq, &phydev->phy_queue); return irq_handled; } linuxデバイスドライバー -jonathan corbet、alessandro rubini、greg kroah-hartman 必須のlinuxデバイスドライバー -sreekrishnan venkateswaran linuxデバイスドライバーの作成 -jerry cooperstein linuxカーネルモジュールプログラミングガイド -peter jay salzman、michael burian、ori pomerantz linux pcmciaプログラマーズガイド -david hinds linux scsiプログラミングの方法 -heiko eibfeldt posixオペレーティングシステムのシリアルプログラミングガイド -michael r.sweet linuxグラフィックスドライバー:はじめに -stéphanemarchesin linux usbデバイスドライバーのプログラミングガイド -detlef fliegl linuxカーネルデバイスモデル -patrick mochel カーネルネットワーキング(1-> 2-> 3-> ...) 「一族と呼んで、ネットワークと呼んで、部族と呼んで、それを家族と呼んでください。あなたがそれを何と呼んでも、あなたが誰であれ、あなたはそれを必要とします。」 -ジェーンハワード カーネルのパケットウォークスルーを理解することは、カーネルネットワークを理解するための鍵です。 netfilterやipsecの内部などを理解するには、それを理解することが不可欠です。 linuxカーネルネットワークレイヤーの最も重要な2つの構造は、struct sk_buffとstruct net_deviceです。static inline int sk_hashed(const struct sock *sk) { return !sk_unhashed(sk); } linuxネットワーク内部の理解 -christian benvenuti linuxカーネルネットワーキング:実装と理論 -rami rosen nixネットワークプログラミング -w。リチャードスティーブンス linuxネットワークプログラミングの決定的なガイド -キールデイビス、ジョンw.ターナー、ネイサンヨーコム linux tcp/ipスタック:組み込みシステムのネットワーク -thomas f. herbert 例によるlinuxソケットプログラミング -warren w. gay linux advanced routing&traffic control howto -bert hubert カーネルデバッグ(1-> 4-> 9-> ...) それと通信するときに、自分が何を意味するかを正確に述べない限り、トラブルは必ず発生します。 〜アラン・チューリング、コンピューターについて ブライアンw.カーニハンは、unix for beginners(1979)のペーパーで、「最も効果的なデバッグツールは、慎重に考えられ、慎重に配置された印刷ステートメントと相まって」と述べています。何を収集するかを知ることは、迅速な診断のために適切なデータをすばやく取得するのに役立ちます。偉大なコンピューター科学者であるedsger dijkstraはかつて、テストはバグの存在を示すことができるが、バグがないことを示すことができると述べました。優れた調査手法は、問題を迅速に解決する必要性、スキルを構築する必要性、主題の専門家の効果的な使用のバランスをとる必要があります。あなたが岩底にぶつかる時があります、何もうまくいかないようで、あなたはすべての選択肢を使い果たします。その後、実際のデバッグが始まります。バグは、効果のないソリューションの修正から解放するために必要な中断をもたらす可能性があります。 ビデオレクチャーカーネルデバッグとプロファイリング 、 コアダンプ分析 、 マルチコアデバッグgdbを使用 、 マルチコアレース状態の制御 、 デバッグエレクトロニクス /* buggy code -- stack frame problem * if you require information, do not free memory containing the information */ char *initialize() { char string[80]; char* ptr = string; return ptr; } int main() { char *myval = initialize(); do_something_with(myval); } /* “when debugging, novices insert corrective code; experts remove defective code.” * – richard pattis #if debug printk("the above can be considered as development and review in industrial practises"); #endif */ linuxデバッグおよびパフォーマンスチューニング -steve best linuxアプリケーションのデバッグ手法 -aurelian melinte gdbを使用したデバッグ:gnuソースレベルのデバッガー -roland h. pesch デバッグ組み込みlinux -クリストファーハリナン the art of debugging with gdb、ddd、and eclipse -ノーマンs.マトロフ プログラムが失敗する理由:体系的なデバッグのガイド -andreas zeller software exorcism:レガシーコードのデバッグと最適化のためのハンドブック -bill blunden デバッグ:最もわかりにくいソフトウェアとハードウェアの問題を見つける -david j. agans 思考によるデバッグ:学際的なアプローチ -robert charles metzger バグを見つける:不正なプログラムの本 -adam barr ファイルシステム(1-> 2-> 6-> ...) 「少なくともファイルシステムと結合されているため、仮想メモリが必要でした。」 -ケントンプソン unixシステムでは、すべてがファイルです。何かがファイルでない場合は、名前付きパイプとソケットを除いて、それはプロセスです。ファイルシステムでは、ファイルはinodeで表されます。これは、ファイルを構成する実際のデータに関する情報を含む一種のシリアル番号です。 linux仮想ファイルシステムvfsは、マウントされて使用されるときに、各ファイルシステムの情報をメモリにキャッシュします。これらのキャッシュ内のデータは、ファイルとディレクトリが作成、書き込み、削除されるときに変更されるため、ファイルシステムを正しく更新するように細心の注意を払う必要があります。これらのキャッシュの最も重要なものは、個々のファイルシステムが基盤となるブロックストレージデバイスにアクセスする方法に統合されているバッファキャッシュです。 ビデオレクチャーon storage systems 、 flash friendly file system long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) { struct open_flags op; int fd = build_open_flags(flags, mode, &op); struct filename *tmp; if (fd) return fd; tmp = getname(filename); if (is_err(tmp)) return ptr_err(tmp); fd = get_unused_fd_flags(flags); if (fd >= 0) { struct file *f = do_filp_open(dfd, tmp, &op); if (is_err(f)) { put_unused_fd(fd); fd = ptr_err(f); } else { fsnotify_open(f); fd_install(fd, f); } } putname(tmp); return fd; } syscall_define3(open, const char __user *, filename, int, flags, umode_t, mode) { if (force_o_largefile()) flags |= o_largefile; return do_sys_open(at_fdcwd, filename, flags, mode); } linuxファイルシステム -moshe bar linuxファイルシステム -william von hagen nixファイルシステム:進化、設計、および実装 -steve d. pate 実用的なファイルシステムの設計 -dominic giampaolo ファイルシステムフォレンジック分析 -ブライアンキャリア linuxファイルシステム階層 -binh nguyen btrfs:linux bツリーファイルシステム -ohad rodeh stegfs:linuxのステガノグラフィックファイルシステム -andrew d. mcdonald、markus g.kuhn セキュリティ(1-> 2-> 8-> 4-> 3-> ...) 「unixは、ユーザーが愚かなことをするのを止めるようには設計されていません。 —ダググウィン 使用しないと機能しません。倫理はテクノロジーによって変化します。 「f×s = k」自由とセキュリティの積は定数です。 -ニヴェンの法則 暗号はオンラインでの信頼の基礎を形成します。ハッキングとは、技術的、物理的、または人間ベースの要素でセキュリティ制御を悪用することです。実行中の他のプログラムからカーネルを保護することは、安全で安定したシステムに向けた最初のステップですが、これは明らかに十分ではありません。異なるユーザーランドアプリケーションの間にもある程度の保護が必要です。エクスプロイトは、ローカルまたはリモートのサービスを標的にすることができます。 「あなたの運命、力ずくをハッキングすることはできません...バックドア、ライフへのサイドチャネルが必要です。」―クライドドゥーザ コンピュータは問題を解決せず、解決策を実行します。すべての non-deterministic アルゴリズムコードの背後には、 determined の考え方があります。 -/ var/log/dmesg ビデオ講義暗号化とネットワークセキュリティ 、 セキュリティのための名前空間 、 保護リモート攻撃 、 secure embedded linux env x='() { :;}; echo vulnerable' bash -c "echo this is a test for shellsock" ハッキング:搾取の芸術 -ジョン・エリクソン ルートキットアーセナル:システムの暗いコーナーでのエスケープと回避 -bill blunden 公開されたハッキング:ネットワークセキュリティの秘密 -stuart mcclure、joel scambray、george kurtz カーネル活用のガイド:コアへの攻撃 -enrico perla、massimiliano oldani the art of memory forensics -michael hale ligh、andrew case、jamie levy、aaron walters 実用的なリバースエンジニアリング -bruce dang、alexandre gazet、elias bachaalany 実用的なマルウェア分析 -michael sikorski、andrew honig 最大linuxセキュリティ:linuxサーバーを保護するためのハッカーのガイド -anonymous linuxセキュリティ -クレイグハント real world linux security -ボブ・トクセン カーネルソース(0.11-> 2.4-> 2.6-> 3.18) 「ワインのように、カーネルプログラミングの習熟は時間とともに成熟します。しかし、ワインとは異なり、その過程でより甘くなります。」 -ローレンス・ムチェカ プログラマーはアーティストだとは思わないかもしれませんが、プログラミングは非常にクリエイティブな職業です。それは論理ベースの創造性です。コンピューターサイエンスの教育では、ブラシや顔料を研究することで、誰かを専門家の画家にする以上に、専門家のプログラマーになることはできません。すでにご存じのとおり、道を知ることと道を歩くことには違いがあります。カーネルのソースコードを手に取り、手を汚すことが最も重要です。最後に、このようにして得たカーネルknowledgeを使用すると、どこに行っても、shineになります。未熟なコーダーは模倣します。成熟したコーダーが盗む;悪いコーダーは彼らが取るものを汚し、良いコーダーはそれをより良いもの、または少なくとも何か違うものに変えます。良いコーダーは彼の盗難を、それが引き裂かれたものとは全く異なる独特の感覚に溶け込ませます。 ビデオレクチャーカーネルレシピ linux-0.11 ├── boot │ ├── bootsect.s head.s setup.s ├── fs │ ├── bitmap.c block_dev.c buffer.c char_dev.c exec.c │ ├── fcntl.c file_dev.c file_table.c inode.c ioctl.c │ ├── namei.c open.c pipe.c read_write.c │ ├── stat.c super.c truncate.c ├── include │ ├── a.out.h const.h ctype.h errno.h fcntl.h │ ├── signal.h stdarg.h stddef.h string.h termios.h │ ├── time.h unistd.h utime.h │ ├── asm │ │ ├── io.h memory.h segment.h system.h │ ├── linux │ │ ├── config.h fdreg.h fs.h hdreg.h head.h │ │ ├── kernel.h mm.h sched.h sys.h tty.h │ ├── sys │ │ ├── stat.h times.h types.h utsname.h wait.h ├── init │ └── main.c ├── kernel │ ├── asm.s exit.c fork.c mktime.c panic.c │ ├── printk.c sched.c signal.c sys.c system_calls.s │ ├── traps.c vsprintf.c │ ├── blk_drv │ │ ├── blk.h floppy.c hd.c ll_rw_blk.c ramdisk.c │ ├── chr_drv │ │ ├── console.c keyboard.s rs_io.s │ │ ├── serial.c tty_io.c tty_ioctl.c │ ├── math │ │ ├── math_emulate.c ├── lib │ ├── close.c ctype.c dup.c errno.c execve.c _exit.c │ ├── malloc.c open.c setsid.c string.c wait.c write.c ├── makefile ├── mm │ ├── memory.c page.s └── tools └── build.c 初心者は linux 0.11ソース (20,000行未満のソースコード)から始めます。 linux 0.11と比較して20年の開発後、linuxは非常に巨大で複雑なものになり、習得が困難になりました。ただし、デザインコンセプトと主要な構造には基本的な変更はありません。 linux 0.11を学ぶことはまだ重要な実用的意義を持っています。 カーネルハッカーの必須の読み取り=> linux_source_dir/documentation/* 少なくとも1つのカーネルメーリングリストに登録し、アクティブである必要があります。 kernel newbies で始めます。 ソースコード全体を読む必要はありません。カーネルapiとその使用法に慣れたら、関心のあるサブシステムのソースコードから直接始めてください。独自のプラグアンドプレイモジュールを記述してカーネルを試すこともできます。 デバイスドライバーの作成者は、専用のハードウェアを用意することでメリットを得られます。 raspberry pi から始めます。