web-dev-qa-db-ja.com

Linuxカーネル:初心者向けチュートリアル

個人的な楽しみのために、カーネルの内部の変更、パッチの適用、デバイスドライバーとモジュールの処理に興味があります。

経験豊富なプログラマ向けのカーネルハッキングに関する包括的なリソースはありますか?

52
Adam Matan
**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ランダム化アルゴリズム

Solovay Strassen Derandomized Algorithm for Primality Test

矛盾しないように読んでください。信じて当然のことと考えてはいけません。話や談話を見つけることも、しかし、検討して検討します。味わう本、飲み込む本、噛んで消化する本の一部:つまり、一部しか読んでいない本、読んでいるが不思議ではない本、完全に読んでいる本、そして勤勉さと注意をもって。

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
  1. Linuxカーネル開発 -Robert Love
  2. Linuxカーネルの理解 -Daniel P. Bovet、Marco Cesati
  3. The Linux of KerneL Design -Yang Lixiang
  4. Professional Linux Kernel Architecture -Wolfgang Mauerer
  5. NIXオペレーティングシステムの設計 -モーリスJ.バッハ
  6. Linux Virtual Memory Managerについて -Mel Gorman
  7. Linuxカーネル内部 -Tigran Aivazian
  8. Embedded Linux Primer -クリストファーハリナン

Linuxデバイスドライバー(1-> 2-> 4-> 3-> 8-> ...)

「音楽はあなたを運ばない。感情や物語の小さな小さな核に本当に集中するあなたの能力によって、あなたは厳密にそれを運ばなければならない」。 -デビーハリー

あなたの仕事は基本的にハードウェアデバイスとソフトウェアカーネルの間の高速通信インターフェースを確立することです。ハードウェアリファレンスデータシート/マニュアルを読んで、デバイスの動作、デバイスの制御とデータの状態、および提供されている物理チャネルを理解する必要があります。特定のアーキテクチャのアセンブリに関する知識と、VHDLやVerilogなどのVLSIハードウェア記述言語に関する公正な知識があれば、長期的に役立ちます。

[〜#〜] q [〜#〜]:しかし、なぜハードウェアの仕様を読まなければならないのですか?

[〜#〜] a [〜#〜]:なぜなら、「ソフトウェアがブリッジできないカーボンとシリコンの裂け目がある」-Rahulソナド

ただし、上記はComputational AlgorithmsDriver 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. Linuxデバイスドライバー -Jonathan Corbet、Alessandro Rubini、Greg Kroah-Hartman
  2. 必須のLinuxデバイスドライバー -Sreekrishnan Venkateswaran
  3. Linuxデバイスドライバーの作成 -Jerry Cooperstein
  4. Linuxカーネルモジュールプログラミングガイド -Peter Jay Salzman、Michael Burian、Ori Pomerantz
  5. Linux PCMCIAプログラマーズガイド -David Hinds
  6. Linux SCSIプログラミングの方法 -Heiko Eibfeldt
  7. POSIXオペレーティングシステムのシリアルプログラミングガイド -Michael R.Sweet
  8. Linuxグラフィックスドライバー:はじめに -StéphaneMarchesin
  9. Linux USBデバイスドライバーのプログラミングガイド -Detlef Fliegl
  10. Linuxカーネルデバイスモデル -Patrick Mochel

カーネルネットワーキング(1-> 2-> 3-> ...)

「一族と呼んで、ネットワークと呼んで、部族と呼んで、それを家族と呼んでください。あなたがそれを何と呼んでも、あなたが誰であれ、あなたはそれを必要とします。」 -ジェーンハワード

カーネルのパケットウォークスルーを理解することは、カーネルネットワークを理解するための鍵です。 NetfilterやIPSecの内部などを理解するには、それを理解することが不可欠です。 Linuxカーネルネットワークレイヤーの最も重要な2つの構造は、struct sk_buffstruct net_deviceです。

static inline int sk_hashed(const struct sock *sk)
{
        return !sk_unhashed(sk);
} 
  1. Linuxネットワーク内部の理解 -Christian Benvenuti
  2. Linuxカーネルネットワーキング:実装と理論 -Rami Rosen
  3. NIXネットワークプログラミング -W。リチャードスティーブンス
  4. Linuxネットワークプログラミングの決定的なガイド -キールデイビス、ジョンW.ターナー、ネイサンヨーコム
  5. Linux TCP/IPスタック:組み込みシステムのネットワーク -Thomas F. Herbert
  6. 例によるLinuxソケットプログラミング -Warren W. Gay
  7. 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
 */
  1. Linuxデバッグおよびパフォーマンスチューニング -Steve Best
  2. Linuxアプリケーションのデバッグ手法 -Aurelian Melinte
  3. GDBを使用したデバッグ:GNUソースレベルのデバッガー -Roland H. Pesch
  4. デバッグ組み込みLinux -クリストファーハリナン
  5. The Art of Debugging with GDB、DDD、and Eclipse -ノーマンS.マトロフ
  6. プログラムが失敗する理由:体系的なデバッグのガイド -Andreas Zeller
  7. Software Exorcism:レガシーコードのデバッグと最適化のためのハンドブック -Bill Blunden
  8. デバッグ:最もわかりにくいソフトウェアとハ​​ードウェアの問題を見つける -David J. Agans
  9. 思考によるデバッグ:学際的なアプローチ -Robert Charles Metzger
  10. バグを見つける:不正なプログラムの本 -Adam Barr

ファイルシステム(1-> 2-> 6-> ...)

「少なくともファイルシステムと結合されているため、仮想メモリが必要でした。」 -ケントンプソン

UNIXシステムでは、すべてがファイルです。何かがファイルでない場合は、名前付きパイプとソケットを除いて、それはプロセスです。ファイルシステムでは、ファイルはinodeで表されます。これは、ファイルを構成する実際のデータに関する情報を含む一種のシリアル番号です。 Linux仮想ファイルシステムVFSは、マウントされて使用されるときに、各ファイルシステムの情報をメモリにキャッシュします。これらのキャッシュ内のデータは、ファイルとディレクトリが作成、書き込み、削除されるときに変更されるため、ファイルシステムを正しく更新するように細心の注意を払う必要があります。これらのキャッシュの最も重要なものは、個々のファイルシステムが基盤となるブロックストレージデバイスにアクセスする方法に統合されているバッファキャッシュです。

ビデオレクチャーon Storage SystemsFlash 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. Linuxファイルシステム -Moshe Bar
  2. Linuxファイルシステム -William Von Hagen
  3. NIXファイルシステム:進化、設計、および実装 -Steve D. Pate
  4. 実用的なファイルシステムの設計 -Dominic Giampaolo
  5. ファイルシステムフォレンジック分析 -ブライアンキャリア
  6. Linuxファイルシステム階層 -Binh Nguyen
  7. BTRFS:Linux Bツリーファイルシステム -Ohad Rodeh
  8. 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"
  1. ハッキング:搾取の芸術 -ジョン・エリクソン
  2. ルートキットアーセナル:システムの暗いコーナーでのエスケープと回避 -Bill Blunden
  3. 公開されたハッキン​​グ:ネットワークセキュリティの秘密 -Stuart McClure、Joel Scambray、George Kurtz
  4. カーネル活用のガイド:コアへの攻撃 -Enrico Perla、Massimiliano Oldani
  5. The Art of Memory Forensics -Michael Hale Ligh、Andrew Case、Jamie Levy、AAron Walters
  6. 実用的なリバースエンジニアリング -Bruce Dang、Alexandre Gazet、Elias Bachaalany
  7. 実用的なマルウェア分析 -Michael Sikorski、Andrew Honig
  8. 最大Linuxセキュリティ:Linuxサーバーを保護するためのハッカーのガイド -Anonymous
  9. Linuxセキュリティ -クレイグハント
  10. 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
  1. 初心者は Linux 0.11ソース (20,000行未満のソースコード)から始めます。 Linux 0.11と比較して20年の開発後、Linuxは非常に巨大で複雑なものになり、習得が困難になりました。ただし、デザインコンセプトと主要な構造には基本的な変更はありません。 Linux 0.11を学ぶことはまだ重要な実用的意義を持っています。
  2. カーネルハッカーの必須の読み取り=> Linux_source_dir/Documentation/*
  3. 少なくとも1つのカーネルメーリングリストに登録し、アクティブである必要があります。 kernel newbies で始めます。
  4. ソースコード全体を読む必要はありません。カーネルAPIとその使用法に慣れたら、関心のあるサブシステムのソースコードから直接始めてください。独自のプラグアンドプレイモジュールを記述してカーネルを試すこともできます。
  5. デバイスドライバーの作成者は、専用のハードウェアを用意することでメリットを得られます。 Raspberry Pi から始めます。
33
manav m-n

Linuxカーネル初心者 は素晴らしいリソースです。

12
Hemant

Greg Kroah-Hartmanによる " Linux Kernel in a Nutshell "と " nderstanding the Linux Kernel "によるRobert Loveを読むことをお勧めします。読む必要があります:)

5
wzzrd

Linuxデバイスドライバー は、別の優れたリソースです。それはあなたに内部の仕組みに入る別の方法を与えるでしょう。序文から:

これは表面的には、Linuxシステム用のデバイスドライバの記述に関する本です。もちろん、それは価値のある目標です。新しいハードウェア製品の流れがすぐに遅くなる可能性は低く、誰かがこれらすべての新しいガジェットをLinuxで動作させる必要があります。しかし、この本はLinuxカーネルがどのように機能するか、そしてその動作をあなたのニーズや興味にどのように適応させるかについても述べています。 Linuxはオープンシステムです。この本があれば、より多くの開発者コミュニティがよりオープンでアクセスしやすくなることを願っています。

4
Larry Smithmier

Linux Documentation Project を参照してください。特に「Linuxカーネルモジュールガイド」。

2
wazoox

Linux Kernel 2.4 Internals は、もう1つのオンラインリソースです。起動から始めて、かなり「根本的な」アプローチを取るようです。ここに目次:

  1. 起動
    • 1.1 Linuxカーネルイメージのビルド
    • 1.2起動:概要
    • 1.3起動:BIOS POST
    • 1.4ブート:ブートセクターとセットアップ
    • 1.5ブートローダーとしてのLILOの使用
    • 1.6高レベルの初期化
    • 1.7 x86でのSMPブートアップ
    • 1.8初期化データとコードの解放
    • 1.9カーネルコマンドラインの処理
  2. プロセスおよび割り込み管理
    • 2.1タスク構造とプロセステーブル
    • 2.2タスクとカーネルスレッドの作成と終了
    • 2.3 Linuxスケジューラ
    • 2.4 Linuxリンクリストの実装
    • 2.5待機キュー
    • 2.6カーネルタイマー
    • 2.7下半分
    • 2.8タスクキュー
    • 2.9タスクレット
    • 2.10 Softirqs
    • 2.11 i386アーキテクチャでのシステムコールの実装方法
    • 2.12原子操作
    • 2.13スピンロック、読み書きスピンロック、ビッグリーダースピンロック
    • 2.14セマフォと読み取り/書き込みセマフォ
    • 2.15モジュールをロードするためのカーネルサポート
  3. 仮想ファイルシステム(VFS)
    • 3.1 InodeキャッシュとDcacheとの相互作用
    • 3.2ファイルシステムの登録/登録解除
    • 3.3ファイル記述子の管理
    • 3.4ファイル構造の管理
    • 3.5スーパーブロックとマウントポイントの管理
    • 3.6仮想ファイルシステムの例:pipefs
    • 3.7ディスクファイルシステムの例:BFS
    • 3.8実行ドメインとバイナリ形式
  4. Linuxページキャッシュ
  5. IPCメカニズム
    • 5.1セマフォ
    • 5.2メッセージキュー
    • 5.3共有メモリ
    • 5.4 Linux IPCプリミティブ

そして、さらに甘くするために、Robert Loveによる新しいLinux Kernel Development Third Editionがあり、 Slashdotにレビューがあります

2
Larry Smithmier

Claudia SalzbergらによるLinux Kernel Primerから始めます。初心者のために始めるのに良いもの。ロバート・ラブの本は、初心者が最初から始めるべき本ではありません。後者の本は中級以上です。

1
PaulDaviesC