KVM のソースを呼んでる中で anon_inode_getfd という API を知ったので、 KVM のソースコードを写経しながらカーネルモジュールを作ってみた
... といってもユーザランドに向けて ioctl(2) のインタフェースを作るだけのモジュールで実用的なものでない。KVM API を理解するための写経 📝
デモ
モジュールを make して insmod すると /dev/hiboma
が生える
$ sudo make make -C /lib/modules/3.10.0-327.36.3.el7.x86_64/build SUBDIRS=/vagrant/kernel_module_scratch/anon_inode_getfile modules make[1]: ディレクトリ `/usr/src/kernels/3.10.0-327.36.3.el7.x86_64' に入ります CC [M] /vagrant/kernel_module_scratch/anon_inode_getfile/anon_inode_getfile.o Building modules, stage 2. MODPOST 1 modules CC /vagrant/kernel_module_scratch/anon_inode_getfile/anon_inode_getfile.mod.o LD [M] /vagrant/kernel_module_scratch/anon_inode_getfile/anon_inode_getfile.ko make[1]: ディレクトリ `/usr/src/kernels/3.10.0-327.36.3.el7.x86_64' から出ます
$ sudo make insmod insmod anon_inode_getfile.ko
$ ls -hal /dev/hiboma crw-------. 1 root root 10, 232 11月 18 12:35 /dev/hiboma
おまけで、dmesg にはこんなログを残す
[ 3232.721279] registerd /dev/hiboma [ 3269.707282] deregisterd /dev/hiboma
/dev/hiboma
を open(2) して ioctl(2) すると anon_inode デスクリプタが返ってくる。このデスクリプタに ioctl(2) を呼ぶとあれこれできる
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <err.h> #define HIBOMA_GET_VERSION 0 #define HIBOMA_OPEN_FD 1 int main() { int fd = open("/dev/hiboma", O_RDONLY|O_WRONLY); if ( fd < 0) { perror("failed to open /dev/hiboma"); return 1; } int r = ioctl(fd, HIBOMA_GET_VERSION); if (r < 0 ) { perror("ioctl"); return EXIT_FAILURE; } printf("version = %d\n", r); r = ioctl(fd, HIBOMA_OPEN_FD); if (r < 0 ) { perror("ioctl"); return EXIT_FAILURE; } printf("fd = %d\n", r); r = ioctl(fd, HIBOMA_OPEN_FD); if (r < 0 ) { perror("ioctl"); return EXIT_FAILURE; } printf("fd = %d\n", r); char command[32]; snprintf(command, sizeof(command), "ls -hal /proc/%d/fd", getpid()); system(command); exit(EXIT_SUCCESS); }
/proc/$pid/fd
でデスクリプタを見ると、キャラクタデバイスと anon_inode: プレフィクスを持つデスクリプタが見える。
dr-x------. 2 root root 0 11月 18 09:19 . dr-xr-xr-x. 9 root root 0 11月 18 09:19 .. lrwx------. 1 root root 64 11月 18 09:19 0 -> /dev/pts/0 lrwx------. 1 root root 64 11月 18 09:19 1 -> /dev/pts/0 lrwx------. 1 root root 64 11月 18 09:19 2 -> /dev/pts/0 l-wx------. 1 root root 64 11月 18 09:19 3 -> /dev/hiboma 🍣 lrwx------. 1 root root 64 11月 18 09:19 4 -> anon_inode:hiboma-anon 🍣 lrwx------. 1 root root 64 11月 18 09:19 5 -> anon_inode:hiboma-anon 🍣
面白い
「キャラクタデバイス /dev/kvm を open(2) + ioctl(2) すると anon_inode のデスクリプタを返し、anon_inode デスクリプタを ioctl(2) すると VM や vCPU を操作できる 」のが KVM の基調となるインタフェースで、ここでやっていることと設計は一緒 (真似してコピペで作ってるから当然なんだけどね! )
miscdevice と anon_inode
/dev/hiboma
キャラクタデバイスは下記の API で作っている
int misc_register(struct miscdevice * misc,)
ioctl(2) が返す anon_inode のデスクリプタは下記の API で作れる
int anon_inode_getfd(const char *name, const struct file_operations *fops, void *priv, int flags)
anon_inode_getfd が返すファイルディスクリプタは、 anon_inodefs* という疑似ファイルシステムから割り当てられた inode を指す
- anon_inodefs の解説は anon_inodefs - Linuxの備忘録とか・・・(目次へ) を読むのがよいかな。 ( いつも読んでます。お世話になっております )
- その他の疑似ファイルシステム(tmpfs, procfs, debugfs, sysfs ... ) なんかとの違いや pros / cons を把握できるとよさそう
miscdevice についても miscキャラクタデバイス - Linuxの備忘録とか・・・(目次へ) を読むのがよい