個人的な楽しみのために、カーネルの内部の変更、パッチの適用、デバイスドライバーとモジュールの処理に興味があります。
経験豊富なプログラマ向けのカーネルハッキングに関する包括的なリソースはありますか?
**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デバイスドライバー(1-> 2-> 4-> 3-> 8-> ...)
「音楽はあなたを運ばない。感情や物語の小さな小さな核に本当に集中するあなたの能力によって、あなたは厳密にそれを運ばなければならない」。 -デビーハリー
あなたの仕事は基本的にハードウェアデバイスとソフトウェアカーネルの間の高速通信インターフェースを確立することです。ハードウェアリファレンスデータシート/マニュアルを読んで、デバイスの動作、デバイスの制御とデータの状態、および提供されている物理チャネルを理解する必要があります。特定のアーキテクチャのアセンブリに関する知識と、VHDLやVerilogなどのVLSIハードウェア記述言語に関する公正な知識があれば、長期的に役立ちます。
[〜#〜] 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;
}
カーネルネットワーキング(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);
}
カーネルデバッグ(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
*/
ファイルシステム(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);
}
セキュリティ(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"
カーネルソース(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_source_dir/Documentation/*
Linuxカーネル初心者 は素晴らしいリソースです。
Greg Kroah-Hartmanによる " Linux Kernel in a Nutshell "と " nderstanding the Linux Kernel "によるRobert Loveを読むことをお勧めします。読む必要があります:)
Linuxデバイスドライバー は、別の優れたリソースです。それはあなたに内部の仕組みに入る別の方法を与えるでしょう。序文から:
これは表面的には、Linuxシステム用のデバイスドライバの記述に関する本です。もちろん、それは価値のある目標です。新しいハードウェア製品の流れがすぐに遅くなる可能性は低く、誰かがこれらすべての新しいガジェットをLinuxで動作させる必要があります。しかし、この本はLinuxカーネルがどのように機能するか、そしてその動作をあなたのニーズや興味にどのように適応させるかについても述べています。 Linuxはオープンシステムです。この本があれば、より多くの開発者コミュニティがよりオープンでアクセスしやすくなることを願っています。
Linux Documentation Project を参照してください。特に「Linuxカーネルモジュールガイド」。
Linux Kernel 2.4 Internals は、もう1つのオンラインリソースです。起動から始めて、かなり「根本的な」アプローチを取るようです。ここに目次:
そして、さらに甘くするために、Robert Loveによる新しいLinux Kernel Development Third Editionがあり、 Slashdotにレビューがあります
Claudia SalzbergらによるLinux Kernel Primerから始めます。初心者のために始めるのに良いもの。ロバート・ラブの本は、初心者が最初から始めるべき本ではありません。後者の本は中級以上です。