lLinuxカーネルプログラミングを学びたいです。
そのための出発点は何でしょうか?対象とするより単純な問題のいくつかは何でしょうか?
lLinuxカーネルプログラミングを学びたいです。
そのための出発点は何でしょうか?対象とするより単純な問題のいくつかは何でしょうか?
**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つのステップから始めなければなりません。次のどの本から始めるかについて混乱している場合でも、心配する必要はありません。いずれかを選択してください。さまよう者全員が失われるわけではありません。すべての道路は最終的に高速道路に接続するため、行き止まりに遭遇することなくページが進むにつれて、カーネルジャーニーで新しいことを探索し、最終的にに接続します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();
}
}
Core Linux(5-> 1-> 3-> 2-> 7-> 4-> 6)
「自然にはカーネルもシェルもありません。彼女は一度にすべてです」-ヨハン・ヴォルフガング・フォン・ゲーテ
読者は、オペレーティングシステムの概念に精通している必要があります。実行時間の長いプロセスと、実行のバーストが短いプロセスとの違いについての公正な理解。ソフトおよびハードのリアルタイム制約を満たしながら、フォールトトレランス。n/ack
読んでいる間、コアサブシステムのLinuxカーネルソースによって行われた設計の選択を理解することが重要です。
スレッド[および]シグナルは、プラットフォームに依存する悲惨、絶望、恐怖、狂気の軌跡です(〜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デバイスドライバーに関するビデオレクチャー(レクチャー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-> ...)
それとコミュニケーションをとる際に、自分が何を意味するのかを正確に言わない限り、問題は必ず発生します。〜Alan Turing、コンピューターについて
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
暗号化とネットワークセキュリティ、セキュリティのための名前空間、リモート攻撃からの保護、セキュアな組み込み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カーネルプログラミングに関するRobertLoveの本を手に入れてみてください。その非常に簡潔でわかりやすいです。
その後またはそれに伴い、「Linuxカーネルについて」をご覧になることをお勧めしますが、初期の段階ではお勧めしません。
また、Linuxカーネルプログラミングガイドも参照してください。カーネルモジュールのプログラミングから多くのことを学ぶことができるので、そのガイドはあなたを助けます。はい、多くの情報については、カーネルソースtarballの「documentation」サブディレクトリを参照してください。
Linuxカーネル管理人プロジェクトをチェックしてください
「Linuxカーネルのソースコードを調べ、コードレビューを行い、メンテナンスされていないコードを修正し、その他のクリーンアップとAPI変換を行います。カーネルハッキングの良いスタートです」
私は言わなければならないでしょう:「Cを学ぶ」。:)
この無料のオンラインブックをお試しください。
Linuxカーネルモジュールプログラミングガイド http://www.linuxhq.com/guides/LKMPG/mpg.html
私が読んで非常に役立つと思った次の本:
kernelnewbies.orgを確認し、Kernelnewbiesメーリングリストに登録して、irc.oftc.org#kernelnewbiesにアクセスしてください。
いくつかのリソース: