Linuxカーネルプログラミングを学びたいです。
そのための出発点は何でしょうか?対象とするより単純な問題のいくつかは何でしょうか?
Linuxカーネルプログラミングに関するRobertLoveの本を手に入れてみてください。その非常に簡潔でわかりやすいです。
その後またはそれに伴い、「Linuxカーネルについて」をご覧になることをお勧めしますが、初期段階ではお勧めしません。
また、 Linuxカーネルプログラミングガイド もご覧ください。カーネルモジュールのプログラミングから多くのことを学ぶことができるので、そのガイドが役に立ちます。はい、多くの情報については、カーネルソースtarballの「documentation」サブディレクトリを参照してください。
**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
の推奨書籍「男性は、ある程度の生命が得られるまで本を理解しないか、いずれにせよ、その内容の少なくとも一部を見て生きるまで、深い本を理解する人はいない」。 –エズラパウンド
1000コードマイルの旅は、1つのステップから開始する必要があります。次の本のどれから始めるかについて混乱している場合でも、心配しないで、お好きな本を選んでください。さまよう者全員が失われるわけではありません。 すべての道路が最終的に高速道路に接続するため、行き止まりに遭遇することなくページが進むにつれて、カーネルジャーニーで新しいことを探索し、最終的にcode-set
に接続します。注意深く読んで覚えておいてください:コードは文学ではありません。
残っているのは、物でも、感情でも、イメージでも、精神的な絵でも、記憶でも、アイデアでもありません。機能です。ある種のプロセス。 「より大きな」何かの関数として説明できる人生の側面。したがって、それは実際には他の何かから「分離」されていないように見えます。ナイフの機能のように-何かを切る-実際には、ナイフ自体から分離されていません。この機能は現在使用されている場合と使用されていない場合がありますが、分離されることはありません。
素数性テストのためのソロベイ-シュトラッセン非ランダム化アルゴリズム :
矛盾したり混乱したりしないように読んでください。また、信じて当然のことと考えることもありません。また、話や談話を見つけることもありません。しかし、計量して検討する必要があります。味わう本もあれば、飲み込む本もあれば、噛んで消化する本もあります。つまり、一部の本だけを読む、他の本は読むが不思議ではない、いくつかの本は完全に読む必要があります。 、そして勤勉と注意を払って。
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)
「自然にはカーネルもシェルもありません。彼女は一度にすべてです」-ヨハン・ヴォルフガング・フォン・ゲーテ
読者は オペレーティングシステムの概念 に精通している必要があります。実行時間の長いプロセスと、実行のバーストが短いプロセスとの違いについての公正な理解。ソフトおよびハードのリアルタイム制約を満たしながら、フォールトトレランス。読んでいる間、コアサブシステムのLinuxカーネルソースによって行われた設計上の選択を理解し、n/ack
することが重要です。
スレッド[および]シグナルは、プラットフォームに依存する悲惨、絶望、恐怖、狂気の痕跡です(〜AnthonyBaxte)。そうは言っても、カーネルに飛び込む前に、自己評価型のCエキスパートになる必要があります。また、リンクリスト、スタック、キュー、レッドブラックツリー、ハッシュ関数などについても十分な経験が必要です。
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 Sonnad
ただし、上記は計算アルゴリズム( ドライバーコード -下半分)では問題になりません。処理)、 ユニバーサルチューリングマシン で完全にシミュレートできるため。計算結果が 数学領域 で当てはまる場合、それが 物理領域 でも当てはまるのは確実です。
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-> ...)
それとのコミュニケーションにおいて、それが何を意味するのかを正確に言わない限り、トラブルは必ず結果として生じます。 〜アランチューリング、コンピューターについて
Brian W. Kernighanは、Unix for Beginners(1979)の論文で、「最も効果的なデバッグツールは、慎重に検討し、慎重に配置された印刷ステートメントと組み合わせることです」と述べています。何を収集するかを知っていると、適切なデータをすばやく取得して迅速に診断するのに役立ちます。偉大なコンピューター科学者のエドガー・ダイクストラはかつて、テストはバグの存在を示すことはできるが、バグがないことを示すことはできないと述べました。優れた調査手法は、問題を迅速に解決する必要性、スキルを構築する必要性、および対象分野の専門家の効果的な使用のバランスを取る必要があります。
底を打ったとき、何も機能していないように見え、すべてのオプションが不足することがあります。その後、実際のデバッグが始まります。バグは、効果のないソリューションへの固定から解放するために必要な休憩を提供する可能性があります。
カーネルデバッグとプロファイリングに関するビデオレクチャー 、 コアダンプ分析 、 マルチコアデバッグ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
は、マウントおよび使用時に各ファイルシステムの情報をメモリにキャッシュします。これらのキャッシュ内のデータは、ファイルとディレクトリの作成、書き込み、および削除時に変更されるため、ファイルシステムを正しく更新するには多くの注意が必要です。これらのキャッシュの中で最も重要なのはバッファキャッシュです。これは、個々のファイルシステムが基盤となるブロックストレージデバイスにアクセスする方法に統合されています。
ストレージシステムでのビデオ講義 、 フラッシュフレンドリーファイルシステム
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"自由と安全の積は定数です。 -ニヴェンの法則
暗号化は、オンラインでの信頼の基盤を形成します。ハッキングとは、技術的、物理的、または人間ベースの要素でセキュリティ制御を悪用することです。実行中の他のプログラムからカーネルを保護することは、安全で安定したシステムへの第一歩ですが、これは明らかに十分ではありません。異なるユーザーランドアプリケーション間でもある程度の保護が存在する必要があります。エクスプロイトは、ローカルサービスまたはリモートサービスを標的にすることができます。
「運命をハックすることはできません。ブルートフォース...バックドア、ライフへのサイドチャネルが必要です。」― Clyde Dsouza
コンピュータは問題を解決するのではなく、解決策を実行します。すべての 非決定論的 アルゴリズムコードの背後には、 決定的 マインドがあります。 -/ 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)
「ワインのように、カーネルプログラミングの習得は時間とともに成熟します。しかし、ワインとは異なり、その過程で甘くなります」。 -ローレンス・ムチェカ
プログラマーがアーティストだとは思わないかもしれませんが、プログラミングは非常にクリエイティブな職業です。それは論理ベースの創造性です。コンピュータサイエンスの教育は、ブラシと顔料を研究することで誰かを専門の画家にすることができる以上に、誰もが専門のプログラマーになることはできません。すでにご存知のように、道を知ることと道を歩くことには違いがあります。カーネルソースコードで袖をまくり上げて手を汚すことが最も重要です。最後に、こうして得られたカーネル知識を使用すると、どこに行っても輝きします。
未熟なコーダーは模倣します。成熟したコーダーは盗みます。悪いコーダーは彼らが取るものを汚し、良いコーダーはそれをより良いもの、または少なくとも何か違うものに変えます。優れたコーダーは、盗難を、それが引き裂かれたときとはまったく異なる独特の感覚全体に溶け込ませます。
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カーネル管理人プロジェクト
「Linuxカーネルのソースコードを調べ、コードレビューを行い、メンテナンスされていないコードを修正し、その他のクリーンアップとAPI変換を行います。カーネルハッキングの良いスタートです」
私は言わなければならないでしょう:「Cを学ぶ」。 :)
この無料のオンラインブックをお試しください。
Linuxカーネルモジュールプログラミングガイドhttp://www.linuxhq.com/guides/LKMPG/mpg.html
Kernelnewbies.orgを確認し、Kernelnewbiesメーリングリストに登録して、irc.oftc.org#kernelnewbiesにアクセスしてください。