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

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

バリア指示・同期
|機能単位|主なヘッダやソース|備考|h
|バリア|&ogfile(linux/compiler.h,include/linux/compiler.h);&br;&ogfile(asm/barrier.h,include/asm/barrier.h);|linux/compiler.h は linux/kernel.h より include されます。asm/barrier.h は linux/atomic.h から include されます。|
排他制御
|機能単位|主なヘッダやソース|備考|h
|Spin Lock|&ogfileone(linux/spinlock.h,include/linux/spinlock.h);|使い分けのドキュメントは &ogfiledirect(Documentation/locking/spinlocks.txt);, &ogfiledirect(Documentation/DocBook/kernel-locking/index.html);|
|Semaphore|&ogfileone(linux/semaphore.h,include/linux/semaphore.h);||
|Mutex|&ogfileone(linux/mutex.h,include/linux/mutex.h);||

同期制御、状態変化待ち
|機能単位|主なヘッダやソース|備考|h
|Condition|&ogfileone(linux/wait.h,include/linux/wait.h);||
|Completion|&ogfileone(linux/completion.h,include/linux/completion.h);||

割り込みハンドラ登録・設定
|機能単位|主なヘッダやソース|備考|h
|IRQ class|&ogfileone(linux/interrupt.h,include/linux/interrupt.h);||

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

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

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

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

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

スレッド・軽量処理
|機能単位|主なヘッダやソース|備考|h
|kthread|&ogfileone(linux/kthread.h,include/linux/kthread.h);||
|work queue|&ogfileone(linux/workqueue.h,include/linux/workqueue.h);||
|tasklet|&ogfileone(linux/interrupt.h,include/linux/interrupt.h);|ヘッダファイルは linux/interrupt.h です。この中の &ogdefs(tasklet_init(),tasklet_init); をはじめとする関数群です。|

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

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

Kernel Object
|機能単位|主なヘッダやソース|備考|h
|KObject, Kset|&ogfileone(linux/kobject.h,include/linux/kobject.h);||

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

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

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

基本的なファイルシステムノード
|機能単位|主なヘッダやソース|備考|h
|pipe|&ogfileone(fs/pipe.c);|&ogdefs(poll(select),pipe_poll);の実装、&ogdefs(ioctl FIONREAD の実装,pipe_ioctl); は単純な挙動で特別なデバイスも無い環境でも試せるので参考になるでしょう。|
|eventfd|&ogfileone(fs/eventfd.c);|eventfd, signalfd, timerfd それぞれで system call を実装し、file descriptor を API として提供しています。独自の Kernel API を必要としているならば読んでみるのも良いでしょう。|
|signalfd|&ogfileone(fs/signalfd.c);||
|timerfd|&ogfileone(fs/timerfd.c);||

デバイス登録
|機能単位|主なヘッダやソース|備考|h
|platform|&ogfileone(linux/platform_device.h,include/linux/platform_device.h);|&ogdefs(platform_device_register(),platform_device_register); にてプラットホーム・デバイスを登録します。プラットホームデバイスは SoC に内蔵された IP ブロックが主に対象となります。ただし、suspend、resume、接続、切断 動作に関して何らかの上流バスの支配あるいは管轄下にある場合は、そのバスのデバイスとして登録します。|
|Input, HID|&ogfileone(linux/input.h,include/linux/input.h);&br;&ogfileone(linux/hid.h,include/linux/hid.h);|組み込みでは &ogdefs(input_allocate_device(),input_allocate_device);, &ogdefs(input_register_device(),input_register_device); のほうをよく使うと思います。関数名はデバイス登録を思わせる名前です。実質はドライバ登録に当たります。同じドライバソースの中にキー入力を報告(伝達)する関数 &ogdefs(input_report_key(),input_report_key);, &ogdefs(input_sync(),input_sync); が見つかると思います。&ogdefs(hid_allocate_device(),hid_allocate_device);, &ogdefs(hid_add_device(),hid_add_device);|
|I2C|&ogfileone(linux/i2c.h,include/linux/i2c.h);|I2C 関連の基礎的な用語 Algorithm, Adapter, Driver, Client については &ogfiledirect(Documentation/i2c/summary); にて解説されています。全般的なドキュメントは &ogfileone(Documentation/i2c/); 以下のファイルと API の解説 &ogfiledirect(Documentation/DocBook/device-drivers/i2c.html); を参照してください。&br;多くの場合 &ogdefs(i2c_register_board_info(),i2c_register_board_info); を使ってプラットホームの初期化処理にてデバイスを登録します。動的な登録は &ogdefs(i2c_new_device(),i2c_new_device); で行います。|
|PCI|&ogfileone(linux/pci.h,include/linux/pci.h);|PCI 接続のデバイス登録は SoC メーカーあるいは開発環境を提供したメーカーがすでに初期化処理の中で行うよう実装しているはずです。&ogdefs(pci_common_init(),pci_common_init);, &ogdefs(pcibios_scan_root(),pcibios_scan_root);, &ogdefs(pci_bus_add_devices(),pci_bus_add_devices); 辺りからコードを追跡して確認してください。それでも意図して登録する場合は &ogdefs(pci_bus_add_device(),pci_bus_add_device); の用例を参考にしてください。|
|SDIO|||
|SPI|&ogfileone(linux/spi/spi.h,include/linux/spi/spi.h);|&ogdefs(spi_register_board_info(), spi_register_board_info); を使ってプラットホームの初期化処理にてデバイスを登録します。動的な登録は &ogdefs(spi_alloc_device(),spi_alloc_device);, &ogdefs(spi_add_device(),spi_add_device); で行います。|
|USB|||

ドライバ登録
|機能単位|主なヘッダやソース|備考|h
|platform|&ogfileone(linux/platform_device.h,include/linux/platform_device.h);|&ogdefs(platform_driver_register(),platform_driver_register);, &ogdefs(module_platform_driver(),module_platform_driver);|
|HID|&ogfileone(linux/hid.h,include/linux/hid.h);|&ogdefs(hid_register_driver(),hid_register_driver);, &ogdefs(module_hid_driver(),module_hid_driver);|
|I2C|&ogfileone(linux/i2c.h,include/linux/pci.h);|&ogdefs(i2c_add_driver(),i2c_add_driver);, &ogdefs(module_i2c_driver(),module_i2c_driver);|
|PCI|&ogfileone(linux/pci.h,include/linux/pci.h);|&ogdefs(pci_register_driver(),pci_register_driver);, &ogdefs(module_pci_driver(),module_pci_driver);|
|SDIO|||
|SPI|&ogfileone(linux/spi/spi.h,include/linux/spi/spi.h);|&ogdefs(spi_register_driver(),spi_register_driver);, &ogdefs(module_spi_driver(), module_spi_driver);|
|USB|&ogfileone(linux/usb.h,include/linux/usb.h);|&ogdefs(usb_register(),usb_register);, &ogdefs(module_usb_driver(),module_usb_driver);|

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