Linux Kernel の見取り図

Linux_bigmap_for_driver_developer.png

標準ライブラリ

機能単位主なヘッダやソース備考
型定義linux/types.h
コンパイラは inttypes.h, stdint.h を提供しています。
定数、最大、最小linux/kernel.h
linux/stddef.h
linux/limits.h
linux/sizes.h
uapi/linux/limits.h は linux/limits.h で include します。
構造体オフセットlinux/stddef.h
linux/kernel.h
メンバーからそれを保持する構造体へ変換するマクロ container_of() もここに含めます。
文字linux/ctype.hlinux/ctype.h は1バイト文字(いわゆるASCII)のみ対応です。
文字列・メモリlinux/string.h
linux/glob.h
linux/string_helpers.h
linux/textsearch.h
linux/textsearch_fsm.h
linux/ihex.h
文字列変換linux/kernel.h
linux/parser.h
linux/kernel.h の中で strtoxxx は kstrtoxxx (たとえばkstrtoul() という関数になっています。
書式フォーマットlinux/kernel.hscnprintf() など
計算(数値)linux/kernel.h
linux/math64.h
asm/div64.h
linux/gcd.h
linux/lcm.h
linux/log2.h
linux/mpi.h
asm/div64.h は linux/math64.h から include されます。プロセッサ語長が 32 bit の場合、64bit (long long) 型に対して除算または剰余演算子を使うとリンクに失敗します。64bit 除算ライブラリ do_div() などを使用して下さい。
計算(ビット)linux/bcd.h
linux/bitops.h
asm/bitops.h
linux/bitrev.h
linux/bitmap.h
asm-generic/bitops/const_hweight.h
asm-generic/bitops/ffs.h
asm-generic/bitops/fls.h
asm-generic/bitops/find.h
linux/crc-ccitt.h
linux/crc-itu-t.h
linux/crc-t10dif.h
linux/crc16.h
linux/crc32.h
linux/crc32c.h
linux/crc7.h
linux/crc8.h
asm/bitops.h, asm-generic/bitops/const_hweight.h, asm-generic/bitops/ffs.h, asm-generic/bitops/fls.h, asm-generic/bitops/find.h は linux/bitops.h で include されます。直接 include しないで下さい。
bitops.h はプロセッサ毎に定義されています。
asm-generic/bitops/const_hweight.h はビットを数え上げる計算です。ファイル名に const がついていますが、即値と変数両方に使えるマクロです。gcc の組み込み関数 __builtin_constant_p() を使用して静的な定数と変数に対する計算をそれぞれ最適化しています。
エンディアン変換linux/byteorder/generic.h
linux/swab.h
linux/byteorder/generic.h は関数一覧として挙げてあります。実際は各アーキテクチャに最適な変換処理を利用するので asm/byteorder.h をインクルードします。
アルゴリズムlinux/average.h
linux/bch.h
linux/bpf.h
linux/bsearch.h
linux/btree.h
linux/circ_buf.h
linux/cordic.h
linux/plist.h
linux/sort.h
linux/range.h
linux/rbtree.h
linux/rslib.h
linux/crypto.h
linux/cryptohash.h
linux/cryptouser.h
linux/hash.h
linux/hashtable.h
linux/jhash.h
圧縮linux/lz4.h
linux/lzo.h
linux/xz.h
linux/zlib.h

リンク・リスト

機能単位主なヘッダやソース備考
リスト操作linux/list.hリンク・リスト・メンバーからそれを保持する構造体へ変換するマクロ list_entry()container_of() と同じです。リスト操作に関連するならば list_entry() を使用して下さい。

アトミック操作

機能単位主なヘッダやソース備考
整数linux/atomic.h
asm/atomic.h
asm/atomic.h はプロセッサ毎に定義されています。asm/atomic.h は linux/atomic.h で include されます。
ビットasm/bitops.hasm/bitops.h はプロセッサ毎に定義されています。ヘッダファイルに atomic かどうか書かれています。atomic な関数・マクロは set_bit(), clear_bit(), clear_bit_unlock(), change_bit(), test_and_set_bit(), test_and_set_bit_lock(), test_and_clear_bit(), test_and_change_bit(), test_bit() atomic 関数と混在可 です。asm/bitops.h は linux/bitops.h で include されます。

バリア指示・同期

機能単位主なヘッダやソース備考
バリアlinux/compiler.h
asm/barrier.h
linux/compiler.h は linux/kernel.h より include されます。asm/barrier.h は linux/atomic.h から include されます。

排他制御

機能単位主なヘッダやソース備考
Spin Locklinux/spinlock.h使い分けのドキュメントは Documentation/locking/spinlocks.txt, Documentation/DocBook/kernel-locking/index.html
Semaphorelinux/semaphore.h
Mutexlinux/mutex.h

同期制御、状態変化待ち

機能単位主なヘッダやソース備考
Conditionlinux/wait.h
Completionlinux/completion.h

割り込みハンドラ登録・設定

機能単位主なヘッダやソース備考
IRQ classlinux/interrupt.h

時間待ち、タイマー

機能単位主なヘッダやソース備考
Sleeplinux/delay.hsleep の代表的な関数は msleep() です。実行中のタスクを再スケジュールします。CPU 資源を無駄にしません。割り込み処理中では使えません。
単に別の task に実行を渡す(いわゆる 0 秒待ちをする)場合は schedule() を使用します。
Delaylinux/delay.hdelay 関数は ndelay(), udelay(), mdelay() があります。これらは CPU を空走させて時間待ちを実現します。割り込みハンドラの中でも使えます。しかし、割り込み応答性能を悪化させます。
Timerlinux/timer.h
linux/hrtimer.h

時刻

機能単位主なヘッダやソース備考
jiffieslinux/jiffies.hjiffies の時間的前後関係を判定する場合は、linux/jiffies.h に定義された比較関数・マクロを使用して下さい。
Timelinux/time.h
linux/timekeeping.h
linux/sched.h
linux/sched.h の中に local_clock(), sched_clock() などの時刻関数が入っています。

メモリ確保

機能単位主なヘッダやソース備考
任意サイズlinux/slab.h
ページ単位linux/gfp.h
linux/mm.h
ページ確保: linux/gfp.h:alloc_page() 、ページ・アドレス取得: linux/mm.h:page_address() となっています。

仮想-物理アドレス・マップ、DMA 転送、コピー

機能単位主なヘッダやソース備考
User - Kernel Copyasm/uaccess.h
linux/uaccess.h
asm/uaccess.h は linux/uaccess.h で include されます。copy_to_user(), copy_from_user() などはアーキテクチャに最適な実装がされることがあります。
Virt - Phy map convertasm/io.h
linux/io.h
mach/hardware.h
asm/io.h は linux/io.h で include されます。virt_to_phys(),phys_to_virt() などはアーキテクチャやプラットホームに最適な実装がされることがあります。一部のプラットホームでは周辺 IP block の仮想アドレス割り付けを単純化していて、軽量な実装の IO_ADDRESS(), IOMEM() マクロなどを経由して物理アドレスから仮想アドレスへ変換出来るよう便宜が図られています。
DMA mapping, Address convert, Scatter Gatherasm/dma-mapping.h
asm-generic/dma-mapping-common.h
asm/dma-mapping.h, asm-generic/dma-mapping-common.h は linux/dma-mapping.h で include されます。
アーキテクチャ、プラットホームによっては DMA アドレスと物理アドレスが違っています。phys_to_dma(), dma_to_phys() 関数が用意されています。

メモリ・マップド・デバイス・アクセス

機能単位主なヘッダやソース備考
Read-Writeasm/io.hasm/io.h は linux/io.h で include されます。readb(), writeb(), readw(), writew(), readl(), writel() などメモリにマップされたデバイスをアクセスするための関数がアーキテクチャやプラットホームに最適化されています。

スレッド・軽量処理

機能単位主なヘッダやソース備考
kthreadlinux/kthread.h
work queuelinux/workqueue.h
taskletlinux/interrupt.hヘッダファイルは linux/interrupt.h です。この中の tasklet_init() をはじめとする関数群です。

接続切断通知

機能単位主なヘッダやソース備考
UEventlinux/kobject.hkobject_uevent(), kobject_uevent_env() 関数で kobject (ユーザー・ランド視点で /sys 以下のノード) から uevent を発行します。
External Connector (Switch)linux/extcon.hAndroid で switch と呼ばれていた抽象化デバイスです。Android も extcon に移行しています。コネクタの接続切断、キーボードとして扱わないボタン押しなどを検出して通知します。

リファレンスカウンタ

機能単位主なヘッダやソース備考
kreflinux/kref.hReference Counter を構成するライブラリです。生成したインスタンスの生存期間を参照の有無によって決定する場合に使います。kref_init(), kref_get(), kref_put() が代表的関数です。

Kernel Object

機能単位主なヘッダやソース備考
KObject, Ksetlinux/kobject.h

ノード形成

機能単位主なヘッダやソース備考
VFS(character)linux/fs.h
linux/cdev.h
alloc_chrdev_region(), register_chrdev(), cdev_alloc(), cdev_init(), cdev_add() 辺りから使用例を探ると良いでしょう。
VFS(block)linux/fs.h
linux/genhd.h
register_blkdev(), blk_register_region(), alloc_disk(), add_disk() 辺りから使用例を探ると良いでしょう。
SCSIscsi/scsi.h
scsi/scsi_host.h
scsi/scsi_driver.h
scsi/scsi_device.h
block device として登録するならば SCSI device として登録した方が良い場合もあります。SCSI 周りは記述が多くなるので別記検討中です。
procfslinux/proc_fs.h
sysfslinux/sysfs.h
linux/device.h
linux/moduleparam.h
DEVICE_ATTR() は linux/device.h にあります。module_param() は linux/moduleparam.h にあります。
debugfslinux/debugfs.h

モジュールロード、アンロード、シンボル解決

機能単位主なヘッダやソース備考
Module insmod rmmodkernel/module.cSystem Call として関数は実装されています。Kernel 内部から呼び出すには symbol を リンクできるように修正する必要が有ります。
Symbol lookuplinux/kallsyms.h
linux/license.h
linux/module.h
シンボルのアドレスを取得する symbol_get()symbol_put() は linux/module.h に有ります。シンボルの解決を使うと static link された Kernel からモジュールの関数を呼び出すことができるようになります。ただし、GPL の抜け穴になるような作り込みは慎みましょう。

基本的なドライバ

機能単位主なヘッダやソース備考
Null, Zero, Full, Mem driversdrivers/char/mem.c/dev/null, /dev/zero, /dev/full, /dev/mem の実装です。単純なキャラクタ型デバイスを実装したドライバです。単純ながら興味深い実装になっています。

基本的なファイルシステムノード

機能単位主なヘッダやソース備考
pipefs/pipe.cpoll(select)の実装、ioctl FIONREAD の実装 は単純な挙動で特別なデバイスも無い環境でも試せるので参考になるでしょう。
eventfdfs/eventfd.ceventfd, signalfd, timerfd それぞれで system call を実装し、file descriptor を API として提供しています。独自の Kernel API を必要としているならば読んでみるのも良いでしょう。
signalfdfs/signalfd.c
timerfdfs/timerfd.c

デバイス登録

機能単位主なヘッダやソース備考
platformlinux/platform_device.hplatform_device_register() にてプラットホーム・デバイスを登録します。プラットホームデバイスは SoC に内蔵された IP ブロックが主に対象となります。ただし、suspend、resume、接続、切断 動作に関して何らかの上流バスの支配あるいは管轄下にある場合は、そのバスのデバイスとして登録します。
HIDlinux/hid.hhid_allocate_device(), hid_add_device()
I2Clinux/i2c.hI2C 関連の基礎的な用語 Algorithm, Adapter, Driver, Client については Documentation/i2c/summary にて解説されています。全般的なドキュメントは Documentation/i2c/ 以下のファイルと API の解説 Documentation/DocBook/device-drivers/i2c.html を参照してください。
多くの場合 i2c_register_board_info() を使ってプラットホームの初期化処理にてデバイスを登録します。動的な登録は i2c_new_device() で行います。
PCIlinux/pci.hPCI 接続のデバイス登録は SoC メーカーあるいは開発環境を提供したメーカーがすでに初期化処理の中で行うよう実装しているはずです。pci_common_init(), pcibios_scan_root(), pci_bus_add_devices() 辺りからコードを追跡して確認してください。それでも意図して登録する場合は pci_bus_add_device() の用例を参考にしてください。
SDIOSDIO デバイスは自動でデバイスが登録されます。登録の流れは mmc_detect_change(), (delayed work を挟み) mmc_rescan(), mmc_rescan_try_freq(), mmc_attach_sdio(), mmc_attach_sd(), mmc_attach_mmc(), mmc_add_card() の様になります。
SPIlinux/spi/spi.hspi_register_board_info() を使ってプラットホームの初期化処理にてデバイスを登録します。動的な登録は spi_alloc_device(), spi_add_device() で行います。
USBlinux/usb.h
linux/usb/hcd.h
接続処理(デバイス登録)は自動で行われます。usb_new_device(), hub_port_connect(), usb_hub_create_port_device() とその呼び出し元のコードを探索してみてください。

ドライバ登録

機能単位主なヘッダやソース備考
platformlinux/platform_device.hplatform_driver_register(), module_platform_driver()
I2Clinux/i2c.hi2c_add_driver(), module_i2c_driver()
PCIlinux/pci.hpci_register_driver(), module_pci_driver()
SDIO
SPIlinux/spi/spi.hspi_register_driver(), module_spi_driver()
USBlinux/usb.husb_register(), module_usb_driver()

クラスデバイス登録

機能単位主なヘッダやソース備考
Input, HIDlinux/input.h
linux/hid.h
組み込みでは input_allocate_device(), input_register_device() のほうをよく使うと思います。関数名はデバイス登録を思わせる名前です。実質はドライバ登録に当たります。同じドライバソースの中にキー入力を報告(伝達)する関数 input_report_key(), input_sync() が見つかると思います。hid_allocate_device(), hid_add_device()
hid_register_driver(), module_hid_driver()

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS