0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Linuxカーネルシステムコール解説【Open編】

Posted at

はじめに

こんにちは。Linuxカーネル研究のために無職になった人です。
今、以下のようなLinuxカーネルを解説するサイトを作っているのですが、ちょっと説明がわかりづらい気もしたので、追加説明という意味で記事を書きました。

今後は linux.tokyo に登録するのみならず、1つ1つの linux.tokyo で登録した内容を記事の形で説明していこうと思っています。
そこで、今回は「Open」システムコールから始めようと思います。ちょっと最初の方にやった「Write」とか「Exec」は内容的に未熟である可能性があり、心配なので...
ちょっと記事にlinux.tokyoへのリンクが多くなってしまっているのですが、ご容赦ください。

また、何か間違いがありましたらお気軽にコメントをくださいmm

Openシステムコールの内容

1. do_sys_open

エントリーポイントになる関数。

do_sys_openの中身の構造
do_sys_open
    get_unused_fd_flags
        alloc_fd
            expand_file ⭐︎1
            __set_open_fd ⭐︎2
    do_filp_open
        init_file ⭐︎3
        path_init ⭐︎4
        link_path_walk
            lookup_fast ⭐︎5
            lookup_slow ⭐︎6
        do_dentry_open ⭐︎7
            f->f_op->open ⭐︎8
        set_nameidata
            __set_nameidata ⭐︎9
    fd_install
        files_fdtables ⭐︎10

◾️大枠の流れ

大枠では以下の流れになります。

一:get_unused_fd_flags
未使用の FD 番号を確保。リンク
二:do_filp_open
struct fileの作成。リンク
三:fd_install
確保済み fd と生成された struct file をプロセスのファイルディスクリプタテーブルに結び付け、のちに参照可能にする。リンク

↓ fd確保

1:get_unused_fd_flags > alloc_fd > expand_file
一でfdが足りない場合に、fdtableを動的に拡張し、より多く確保できるようにする。リンク
2:get_unused_fd_flags > alloc_fd > __set_open_fd
一で最終的に「このFDを占有する」と言う状態にする。リンク

↓ struct file確保

3:do_filp_open > init_file
struct fileを初期化する。リンク

↓ パス確保

4:do_filp_open > path_init
起点パス (cwd か root 等) を決定してパス走査の準備を整える。リンク
5:do_filp_open > link_path_walk > lookup_fast
高速でパス解決を最短経路で完了させる試みを行う。リンク
6:do_filp_open > link_path_walk > lookup_slow
lookup_fastでキャッシュ未ヒット時に、パス解決を再度行う。リンク

↓ block層確保

7:do_filp_open > do_dentry_open
struct fileへの情報追加と、block層の確保の入り口。リンク
8:do_filp_open > do_dentry_open > f->f_op->open
ファイルシステム固有のopenハンドラを呼び出し、デバイスやファイルシステム特有の初期化処理を実行する。ext4_file_open等の実装が呼ばれる。リンク

↓ nameidataの確保

9:do_filp_open > set_nameidata > __set_nameidata
nameidata構造体にデータを入れ、名前解決のコンテキストを初期化する。リンク

↓ 最終的な紐付け

10:fd_install > fd_install
確保済み fd と生成された struct file をプロセスのファイルディスクリプタテーブルに結び付け、のちに参照可能にする。リンク

2. ext4_file_open

上記のdo_sys_openの8のf->f_op->openの中身の実装を説明します。

ext4_file_openの中身の構造
ext4_file_open
    ext4_inode_attach_jinode
        jbd2_alloc_inode
        jbd2_journal_init_jbd_inode

◾️実装の流れ

以下の流れになります。

1:jbd2_alloc_inode
ジャーナリング層(JBD2)用のjbd2_inode構造体をメモリ確保し取得する。リンク
2:jbd2_journal_init_jbd_inode
確保したjbd2_inodeとVFS inodeを結び付け、ジャーナルに対して当該inodeを登録する初期化処理。リンク

3. ext4_lookup

上記のdo_sys_openの lookup_slow で lookupをしているが、そのlookupがext4などのファイルシステム依存なので、ここでそのlookupを説明する。

ext4_lookupの中身の構造
ext4_lookup
    ext4_find_inline_entry
        submit_bio ⭐︎1
        ext4_match ⭐︎2
    ext4_dx_find_entry
        ext4_map_blocks ⭐︎3
        find_get_block_common ⭐︎4
        ext4_match ⭐︎5

◾️大枠の流れ

大枠、以下の流れになります。

一:ext4_find_inline_entry
小規模ディレクトリの検索で使われる検索方法。リンク
二:ext4_dx_find_entry
ハッシュインデックス(dx)を有効にしているときに、B-tree 風のインデックスを用いてエントリを高速検索する検索方法。リンク

↓ inline検索

1:ext4_find_inline_entry > submit_bio
準備した BIO をブロック層へ送出し、ディスク読み取りを開始する。リンク
2:ext4_find_inline_entry > ext4_match
ディレクトリエントリの名前が一致するかの確認。リンク

↓ dx検索

3:ext4_dx_find_entry > ext4_map_blocks
論理ブロック番号を物理ブロックに変換し、必要に応じて新規割当も行う。リンク
4:ext4_dx_find_entry > find_get_block_common
指定ブロック番号に対応するbuffer_headをページキャッシュから検索し、保持参照を返す。リンク
5:ext4_dx_find_entry > ext4_match
ディレクトリエントリの名前が一致するかの確認。リンク

結び

ここまで「Open」システムコールを説明しました。
大まかな流れとしては、do_sys_openから「fd確保→struct file確保(ext4_lookup)→パス確保→ブロック層確保(ext4_file_open)→nameidata確保→最終的な紐付け」の流れでした。
次回は長くなりますが「Read」を解説していきます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?