kfifo 試す (4)
早めに目が覚めたのでいぢり始める。
write の中で kfifo 構造体のメンバを printk してたら、release 時に初期化していない事が判明。buffer の中身も微妙。rmmod して insmod したら初期化されているな。当たり前と言えば当たり前か。
で、ごりごりと printk しながら値を確認しているのですが、write は普通に動作している模様。とは言え、一文字づつ入力して中身を確認しただけの話で、まだまだ微妙なソレはあるのでしょうが。
read??
$ tail ./fifo101130
でカタマる。昨晩は kill できなかった記憶がおぼろにあるんですが、一応 kill できた。
んですが、いろいろ確認している内に kill できなくなる。昨晩この挙動を見つつ意識を失なった記憶があるな。やむなく仮想マシンを reboot。
微妙と思いつつも sleep_on を interruptible_sleep_on にしてみる。kill できた。
tail
なかなか出力されぬ、と言いつつ printk の出力によるときちんとデータが扱えている模様。fgets して printf するプログラムを作ってそっちでナニしてみたら出力された。
微妙ですが、現時点のをサラして一旦休憩
#include <linux/module.h> // required by all modules #include <linux/kernel.h> // required by printk() #include <linux/init.h> #include <linux/fs.h> #include <linux/sched.h> #include <asm/uaccess.h> // required by copy_{to_user, from_user} #include <linux/errno.h> #include <linux/kfifo.h> // fifo MODULE_LICENSE("GPL"); #define EOF (-1) #define TRUE 1 #define FALSE 0 #define BUFSIZ 256 #define DRIVERNAME "yamanetoshi" static int fifo_major = 130; static int read_open, write_open; static struct kfifo *fifo_ptr; static spinlock_t fifo_lock; static DECLARE_WAIT_QUEUE_HEAD(queue); static struct task_struct *read_task; static int read_sleep; static const int debugsw = 1; #define DEBUG_OUT(data) \ if(debugsw) \ printk((data)); static int yamanetoshi_open(struct inode *inode, struct file *file) { printk("yamanetoshi_open\n"); printk(" MINOR(inode->i_rdev): %d\n", MINOR(inode->i_rdev)); if(0 == MINOR(inode->i_rdev) % 2) { if(0 == write_open) { write_open++; } else { return -EAGAIN; } } else { if(0 == read_open) { read_task = current; read_open++; } else { return -EAGAIN; } } return 0; } static int yamanetoshi_release(struct inode *inode, struct file *file) { printk("yamanetoshi_close\n"); if(0 == MINOR(inode->i_rdev) % 2) { kfifo_reset(fifo_ptr); write_open = 0; } else { read_open = 0; } return 0; } static ssize_t yamanetoshi_read(struct file *file, char __user *buf, size_t size, loff_t *offset) { int ret = 0, len = 0; unsigned char *ptr = NULL; DEBUG_OUT("read start\n"); if(0 == kfifo_len(fifo_ptr)) { if(0 == write_open) { return 0; } else { read_sleep = TRUE; interruptible_sleep_on(&queue); } } len = kfifo_len(fifo_ptr); if(size>len) size = len; ptr = kmalloc(size, GFP_KERNEL); if(!ptr) return -ENOMEM; ret = kfifo_get(fifo_ptr, ptr, size); /* { int i; for(i = 0; i < size; i++) { printk("ptr[%d] = %x\n", i, ptr[i]); } } */ if(copy_to_user(buf, ptr, ret)) ret = -EFAULT; kfree(ptr); { int i; for(i = 0; i < ret; i++) { printk("ptr[%d] = %02x\n", i, ptr[i]); printk("buf[%d] = %02x\n", i, buf[i]); } } DEBUG_OUT("read end\n"); return ret; } static ssize_t yamanetoshi_write(struct file *file, const char __user *buf, size_t size, loff_t *offset) { int ret = 0, len; unsigned char *ptr = NULL; DEBUG_OUT("write start\n"); len = strlen(buf); if(size>len) size = len; ptr = kmalloc(size, GFP_KERNEL); if(!ptr) return -ENOMEM; memset(ptr, '\0', size); ret = copy_from_user(ptr, buf, size); if(ret) { kfree(ptr); return ret; } ret = kfifo_put(fifo_ptr, ptr, size); /* { int i; for(i = 0; i < fifo_ptr->in; i++) { printk("fifo_ptr->buffer[%d] = %02x\n", i, fifo_ptr->buffer[i]); } } */ kfree(ptr); if(TRUE == read_sleep && NULL != read_task) { read_sleep = FALSE; wake_up_process(read_task); } DEBUG_OUT("write end\n"); return size; } struct file_operations fifo_fops = { .owner = THIS_MODULE, .read = yamanetoshi_read, .write = yamanetoshi_write, .ioctl = NULL, .open = yamanetoshi_open, .release = yamanetoshi_release, }; static int yamanetoshi_init(void) { int ret; printk("initialize the fifo device\n"); ret = register_chrdev(fifo_major, DRIVERNAME, &fifo_fops); if(ret < 0) return ret; if(fifo_major == 0) fifo_major = ret; spin_lock_init(&fifo_lock); fifo_ptr = kfifo_alloc(BUFSIZ, GFP_KERNEL, &fifo_lock); if(IS_ERR(fifo_ptr)) return -ENOMEM; return 0; } static void yamanetoshi_exit(void) { printk("cleanup the fifo device\n"); kfifo_free(fifo_ptr); unregister_chrdev(fifo_major, DRIVERNAME); } module_init(yamanetoshi_init); module_exit(yamanetoshi_exit);
とりあえず、ReadingGauche 方面に去ります。