Linux: /dev/full と カーネルのソースリーディング #3分で

注) /dev/null じゃなくて /dev/full に関するエントリです。

/dev/full は何ですか?

write(2) すると必ず ENOSPC を返すキャラクタデバイスです。

$ echo hello > /dev/full 
-bash: echo: write error: No space left on device

「そういえば、こんなキャラクタデバイスあったな〜」と思って、Linux カーネルのソースを読み直しました

ChatGPT に聞いてソースを調べる

grepGNU Global でシュっと見つからないので、slack-gptカーネルのソースがどこかと聞いたら一発で正解を出してくれた

こちらが slack-gpt が教えてくれた URL です

github.com

/dev/full のソース

/dev/full の write を処理するコードは write_full でした。

static const struct file_operations full_fops = {
    .llseek     = full_lseek,
    .read_iter  = read_iter_zero,
    .write      = write_full, 🤏

};

必ず -ENOSPC をかえす実装になっています。おもしろいですね

static ssize_t write_full(struct file *file, const char __user *buf,
              size_t count, loff_t *ppos)
{
    return -ENOSPC; 🤏
}

なお、/dev/full デバイスの定義は下記の通り。デバイスの初期化コードは長くなりそうなので スキップ

static const struct memdev {
    const char *name;
    umode_t mode;
    const struct file_operations *fops;
    fmode_t fmode;
} devlist[] = {
#ifdef CONFIG_DEVMEM
     [DEVMEM_MINOR] = { "mem", 0, &mem_fops, FMODE_UNSIGNED_OFFSET },
#endif
     [3] = { "null", 0666, &null_fops, FMODE_NOWAIT },
#ifdef CONFIG_DEVPORT
     [4] = { "port", 0, &port_fops, 0 },
#endif
     [5] = { "zero", 0666, &zero_fops, FMODE_NOWAIT },
     [7] = { "full", 0666, &full_fops, 0 }, 🤏
     [8] = { "random", 0666, &random_fops, FMODE_NOWAIT },
     [9] = { "urandom", 0666, &urandom_fops, FMODE_NOWAIT },
#ifdef CONFIG_PRINTK
    [11] = { "kmsg", 0644, &kmsg_fops, 0 },
#endif
};

感想

  • シンプルな実装で面白い。自分でも作れそう
  • 「ソース読むか ... でもどこだろう ...? 」と迷子になったが、ChatGPT のガイドでたどり着けた。

参考

💡 slack-gpt は同僚の P山さんが開発している ChatGPT Slack ボットです

github.com

twitter.com