広告
procインタフェースを利用してユーザランドのアプリケーションとカーネルでデータをやりとりするサンプルです。
具体的には下記のようにechoでリダイレクトした文字列をカーネルで受信して、catで覗くとリダイレクトした文字列が表示されるような簡単なカーネルモジュールを作ります。開発環境はCentOS7です。
完成イメージ
1 2 3 4 |
$ echo "hello" > /proc/example $ cat /proc/example hello $ |
ソースコード
procmod.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
#include <linux/module.h> #include <linux/init.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/string.h> static char example[64] = {0}; static ssize_t example_write( struct file *filp, const char __user *buff, size_t user_len, loff_t *offset ) { size_t len = 0; if (0 != *offset) return -EINVAL; memset(example, 0, sizeof(example)); len = user_len > sizeof(example) ? sizeof(example) : user_len; memcpy(example, buff, len); example[len-1] = '\n'; printk(KERN_INFO "example: wrote - %s", example); return user_len; } /* /proc/exampleの内容を表示 */ static int example_show( struct seq_file *p, void *v) { seq_printf(p, "%s", example); printk(KERN_INFO "example: show - %s", example); return 0; } /* cat /proc/exampleで実行される */ static int example_open( struct inode *inode, struct file *file) { return single_open(file, example_show, NULL); } static const struct file_operations proc_example_operations = { .owner = THIS_MODULE, .open = example_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, .write = example_write, }; /* insmod実行時に呼び出される */ static int proc_example_init(void) { proc_create("example", S_IRUGO | S_IWUGO, NULL, &proc_example_operations); printk(KERN_INFO "example: Module loaded, and created /proc/example\n"); return 0; } /* rmmod実行時に呼び出される */ static void proc_example_exit(void) { remove_proc_entry("example", NULL); printk(KERN_INFO "example: Module unloaded.\n"); } module_init(proc_example_init); module_exit(proc_example_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Example Kernel Module"); |
1 |
Makefile
1 2 3 4 5 |
obj-m := procmod.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean |
実行結果
ビルドしてカーネルモジュールをロードします。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ make make -C /lib/modules/3.10.0-514.26.2.el7.x86_64/build M=/home/user/driver/proc modules make[1]: Entering directory `/usr/src/kernels/3.10.0-514.26.2.el7.x86_64' CC [M] /home/user/driver/proc/procmod.o Building modules, stage 2. MODPOST 1 modules CC /home/user/driver/proc/procmod.mod.o LD [M] /home/user/driver/proc/procmod.ko make[1]: Leaving directory `/usr/src/kernels/3.10.0-514.26.2.el7.x86_64' $ $ sudo insmod procmod.ko $ lsmod |grep procmod procmod 12702 0 |
1 |
ちゃんとアプリ、カーネル間でデータをやりとりできました。
次回は/dev/にスペシャルファイルを作ってアプリとカーネル間でepoll,ioctlを使った通信を試したいと思います。
広告
広告