カーネルプログラミングの学習 [終了]
-
06-09-2019 - |
質問
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
「人間は、ある程度の人生を歩むまでは本を理解できない。あるいは、少なくともその内容の一部を見て、生きてみなければ、どんな人でも深い本を理解することはできない。」–エズラ・パウンド
千の旅 コードマイル 単一のステップから始めなければなりません。次の本のどれから始めればよいか迷った場合でも、心配しないで、いずれかを選んでください。さまよう人全員が道に迷っているわけではありません。として すべての道は最終的には高速道路につながる, 、行き止まりに遭遇することなくページが進むにつれて、カーネル ジャーニーで新しいことを探索し、最終的には 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 )
「自然には核も殻もありません。彼女は同時にすべてだ」 - ヨハン・ヴォルフガング・フォン・ゲーテ
読者は以下のことに精通している必要があります オペレーティング システムの概念;長時間実行されるプロセスと、短期間で実行されるプロセスとの違いについての公正な理解。ソフトおよびハードのリアルタイム制約を満たしながらフォールト トレランスを実現します。読んでいる間、理解することが重要です n/ack
コア サブシステムの Linux カーネル ソースによって行われる設計の選択。
スレッド [および] シグナル [は] プラットフォームに依存する、悲惨、絶望、恐怖、狂気の軌跡です (~Anthony Baxte)。そうは言っても、カーネルに飛び込む前に、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 カーネル開発 - ロバート・ラブ
- Linux カーネルを理解する - ダニエル P.ボヴェ、マルコ・チェザーティ
- Linux カーネル設計の芸術 - ヤン・リーシャン
- プロフェッショナル Linux カーネル アーキテクチャ - ヴォルフガング・マウラー
- UNIX オペレーティング システムの設計 - モーリス J.バッハ
- Linux 仮想メモリ マネージャーについて - メル・ゴーマン
- Linux カーネルの内部構造 - ティグラン・アイヴァジアン
- 組み込み Linux 入門 - クリストファー・ハリナン
Linuxデバイスドライバー ( 1 -> 2 -> 4 -> 3 -> 8 -> ... )
「音楽はあなたを連れて行ってくれません。感情や物語の小さな核だけに本当に集中できる自分の能力によって、それを厳密に実行しなければなりません。」-- デビー・ハリー
あなたのタスクは基本的に、ハードウェア デバイスとソフトウェア カーネルの間に高速通信インターフェイスを確立することです。デバイスの動作、制御およびデータの状態、提供される物理チャネルを理解するには、ハードウェア リファレンス データシート/マニュアルを読む必要があります。特定のアーキテクチャのアセンブリに関する知識と、VHDL や Verilog などの VLSI ハードウェア記述言語に関する十分な知識が長期的に役立ちます。
Q:しかし、なぜハードウェア仕様を読まなければならないのでしょうか?
あ:なぜなら、「ソフトウェアでは埋めることができない炭素とシリコンの溝がある」 - ラーフル・ソナド
ただし、上記のことは問題にはなりません 計算アルゴリズム (ドライバーコード - 下半分の処理)、上で完全にシミュレートできるため、 万能チューリングマシン. 。計算結果が次の条件に当てはまる場合、 数学的領域, 、でもそれが真実であることは確かです。 物理ドメイン.
ビデオ講義 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;
}
- Linuxデバイスドライバー - ジョナサン・コーベット、アレッサンドロ・ルビーニ、グレッグ・クローア=ハートマン
- 必須の Linux デバイス ドライバー - スリークリシュナン ヴェンカテスワラン
- Linux デバイス ドライバーの作成 - ジェリー・クーパースタイン
- Linux カーネル モジュール プログラミング ガイド - ピーター・ジェイ・ザルツマン、マイケル・ブリアン、オリ・ポメランツ
- Linux PCMCIA プログラマーズ ガイド - デビッド・ハインズ
- Linux SCSI プログラミングのハウツー - ハイコ・アイプフェルト
- POSIX オペレーティング システム用シリアル プログラミング ガイド - マイケル R.甘い
- Linux グラフィックス ドライバー:はじめに - ステファン・マルシュサン
- Linux USB デバイスドライバー用プログラミングガイド - デトレフ・フリーグル
- Linux カーネル デバイス モデル - パトリック・モシェル
カーネルネットワーキング ( 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 ネットワークの内部構造を理解する - クリスチャン・ベンヴェヌーティ
- Linux カーネル ネットワーキング:実装と理論 - ラミ・ローゼン
- UNIX ネットワーク プログラミング - W.リチャード・スティーブンス
- Linux ネットワーク プログラミングの決定版ガイド - キア・デイヴィス、ジョン・W.ターナー、ネイサン・ヨコム
- Linux TCP/IP スタック:組み込みシステムのネットワーキング - トーマス F.ハーバート
- 例による Linux ソケット プログラミング - ウォーレン W.ゲイ
- Linux の高度なルーティングとトラフィック制御のハウツー - バート・ヒューバート
カーネルのデバッグ ( 1 -> 4 -> 9 -> ... )
それとコミュニケーションをとる際に、自分の言いたいことを正確に言わない限り、必ずトラブルが発生します。~アラン・チューリング、コンピューターについて
ブライアン W.Kernighan は、Unix for Beginners (1979) という論文の中で、「最も効果的なデバッグ ツールは、慎重に考え、慎重に配置された print ステートメントと組み合わせることです。」と述べています。何を収集すべきかを知っていれば、適切なデータを迅速に取得して迅速な診断を行うことができます。偉大なコンピューター科学者のエドガー・ダイクストラは、テストによってバグの存在は証明できても、バグがないことは証明できないとかつて述べました。適切な調査手法では、問題を迅速に解決する必要性、スキルを構築する必要性、および対象分野の専門家を効果的に活用する必要性のバランスが取れている必要があります。
どん底に落ちて、何もうまくいかないように見え、すべての選択肢がなくなってしまうことがあります。その後、実際のデバッグが始まります。バグは、効果のないソリューションへの執着から解放されるために必要な休憩を提供してくれる場合があります。
ビデオ講義 カーネルのデバッグとプロファイリングについて, コアダンプ分析, 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のデバッグとパフォーマンスのチューニング - スティーブ・ベスト
- Linux アプリケーションのデバッグ手法 - オーレリアン・メリンテ
- GDB を使用したデバッグ:GNU ソースレベル デバッガ - ローランド H.ペシュ
- 組み込み Linux のデバッグ - クリストファー・ハリナン
- GDB、DDD、Eclipse を使用したデバッグの技術 - ノーマン S.マトロフ
- プログラムが失敗する理由:系統的なデバッグのガイド - アンドレアス・ゼラー
- ソフトウェア悪魔払い:レガシーコードのデバッグと最適化のためのハンドブック - ビル・ブランデン
- デバッグ:最もとらえどころのないソフトウェアおよびハードウェアの問題を見つける - デビッド J.アガンス
- 思考によるデバッグ:学際的なアプローチ - ロバート・チャールズ・メッツガー
- バグを見つけてください:間違ったプログラムの本 - アダム・バール
ファイルシステム ( 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);
}
- Linuxファイルシステム - モシェ バー
- Linux ファイルシステム - ウィリアム・フォン・ハーゲン
- UNIX ファイルシステム:進化、設計、実装 - スティーブ D.パテ
- 実践的なファイル システム設計 - ドミニク・ジャンパオロ
- ファイルシステムのフォレンジック分析 - ブライアン・キャリア
- Linux ファイルシステム階層 - ビン・グエン
- BTRFS:Linux B ツリー ファイルシステム - オハド・ロデ
- ステグFS:Linux 用ステガノグラフィック ファイル システム - アンドリュー D.マクドナルド、マーカス G.クーン
安全 ( 1 -> 2 -> 8 -> 4 -> 3 -> ... )
「UNIX は、ユーザーが愚かなことをするのを阻止するように設計されていません。そうすることは、ユーザーが賢いことをすることも阻止することになるからです。」— ダグ・グウィン
どんなテクニックも使わなければ効果はありません。倫理はテクノロジーによって変わります。
"F × S = k「自由と安全の産物は不変です。- ニーブンの法則
暗号化はオンラインの信頼の基礎を形成します。ハッキングとは、技術的、物理的、または人的要素のいずれかにおけるセキュリティ制御を悪用することです。他の実行中のプログラムからカーネルを保護することは、安全で安定したシステムへの第一歩ですが、これだけでは明らかに十分ではありません。異なるユーザーランドアプリケーション間にも、ある程度の保護が存在する必要があります。エクスプロイトは、ローカルまたはリモートのサービスをターゲットにする可能性があります。
「力ずくで運命をハッキングすることはできません...裏口、人生への横道が必要です。」 ― クライド・ドゥーザ
コンピュータは問題を解決するのではなく、解決策を実行するのです。すべての背後に 非決定的 アルゴリズムコードには、 決定した 心。 -- /var/log/dmesg
ビデオ講義 暗号化とネットワークセキュリティについて, セキュリティのための名前空間, リモート攻撃に対する保護, 安全な組み込み Linux
env x='() { :;}; echo vulnerable' bash -c "echo this is a test for Shellsock"
- ハッキング:搾取の芸術 - ジョン・エリクソン
- ルートキットアーセナル:システムの暗い隅での脱出と回避 - ビル・ブランデン
- ハッキングの暴露:ネットワークセキュリティの秘密 - スチュアート・マクルーア、ジョエル・スカンブレー、ジョージ・カーツ
- カーネル悪用のガイド:コアへの攻撃 - エンリコ・ペルラ、マッシミリアーノ・オルダーニ
- 記憶フォレンジックの芸術 - マイケル・ヘイル・リー、アンドリュー・ケース、ジェイミー・レヴィ、AAロン・ウォルターズ
- 実践的なリバースエンジニアリング - ブルース・ダン、アレクサンドル・ガゼ、エリアス・バカアラニー
- 実践的なマルウェア分析 - マイケル・シコースキ、アンドリュー・ホーニッグ
- 最大の Linux セキュリティ:Linux サーバーを保護するためのハッカー ガイド - 匿名
- Linuxのセキュリティ - クレイグ・ハント
- 現実世界の Linux セキュリティ - ボブ・トクセン
カーネルソース ( 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 0.11 ソース (ソースコードは 20,000 行未満)。20 年間の開発を経て、Linux 0.11 と比較すると、Linux は非常に巨大で複雑になり、学習するのが困難になりました。ただし、設計コンセプトや主要構造に基本的な変更はありません。Linux 0.11 を学習することには、依然として重要な実践的意義があります。
- カーネルハッカーの必読書 =>
Linux_source_dir/Documentation/*
- 少なくとも 1 つのカーネル メーリング リストに登録し、アクティブにする必要があります。皮切りに カーネル初心者.
- ソースコード全体を読む必要はありません。カーネル API とその使用法に慣れたら、興味のあるサブシステムのソース コードを直接開始してください。独自のプラグアンドプレイ モジュールを作成してカーネルを実験することから始めることもできます。
- デバイス ドライバーの作成者は、独自の専用ハードウェアを持つことで恩恵を受けます。皮切りに ラズベリーパイ.
チェック Linuxカーネル用務員プロジェクトの
「」私たちは、コードレビューをしてメンテナンスされていないコードを固定し、その他のクリーンアップとAPIの変換を行う、Linuxカーネルのソースコードを通過します。それはハッキングカーネルへの良いスタートです。「」
私なら「Cを勉強しましょう」と言わざるを得ません。:)
この無料のオンライン書籍をお試しください。
Linux カーネル モジュール プログラミング ガイド http://www.linuxhq.com/guides/LKMPG/mpg.html
、kernelnewbies.orgチェックKernelnewbiesメーリングリストを購読、irc.oftc.org #kernelnewbies
になりました