From 3207df143a96c86e406c3c9dc1990a0642b9f98e Mon Sep 17 00:00:00 2001 From: Kyle K Date: Tue, 25 Dec 2012 21:51:47 -0600 Subject: implement write, use semaphores --- Makefile | 5 ++++- debug.c | 3 +-- main.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++----------- main.h | 2 ++ 4 files changed, 65 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 4b897db..eba35e6 100644 --- a/Makefile +++ b/Makefile @@ -24,5 +24,8 @@ KERNELDIR ?= /lib/modules/$(shell uname -r)/build all: make -C $(KERNELDIR) KCPPFLAGS="-I$(CURDIR)" M=$(PWD) modules -clean: +kclean: make -C $(KERNELDIR) M=$(PWD) clean + +clean: + @rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module.symvers modules.order diff --git a/debug.c b/debug.c index 5c746d1..ab0add8 100644 --- a/debug.c +++ b/debug.c @@ -1,5 +1,4 @@ -/* - * debug.c +/* debug.c * * utilize debufs * FIXME: R/W from /sys/kernel/debug/hello/magic doesn't work diff --git a/main.c b/main.c index d791d62..fcd5732 100644 --- a/main.c +++ b/main.c @@ -1,3 +1,23 @@ +/* main.c + * + * r/w /dev/helloc0 character device + * + * to insert module and call mknod run: + * # ./hello_load.sh + * + * to remove module and cleanup run: + * # ./hello_unload.sh + * + * # cat /dev/helloc0 + * # echo -n foobar > /dev/helloc0 + * + * notes: + * - most notes are handwritten in my book, Device Drivers 3rd + * - ssize_t is an int, size_t is unsigned int, be careful + * - compile kernel with frame pointers to get better stack readout in case of an oops + * + */ + #include #include #include @@ -37,31 +57,56 @@ static int hello_create_debugfs(void) static ssize_t hello_read(struct file *filp, char __user *buff, size_t count, loff_t *f_pos) { struct hello_dev *dev = filp->private_data; + ssize_t ret = 0; /* end of file, also in case of out of bound */ + + if (down_interruptible(&dev->sem)) + return -ERESTARTSYS; + + if (*f_pos >= HELLO_KERNEL_BUFF_LEN) + goto out; /* out of bound read */ if (*f_pos + count > HELLO_KERNEL_BUFF_LEN) - count = HELLO_KERNEL_BUFF_LEN - *f_pos; + count = HELLO_KERNEL_BUFF_LEN - *f_pos; /* truncate the read */ - if (count > 0) + if (copy_to_user(buff, dev->hello_buffer + *f_pos, count)) /* write to userspace memory */ { - copy_to_user(buff, dev->hello_buffer + *f_pos, count); - *f_pos += count; /* yes we have to keep track */ - return count; + ret = -EFAULT; + goto out; } - return 0; /* end of file, also in case of out of bound */ + *f_pos += count; /* yes we have to keep track */ + dev->buff_index += count; + ret= count; + + out: + up(&dev->sem); + return ret; } static ssize_t hello_write(struct file *filp, const char __user *buff, size_t count, loff_t *f_pos) { struct hello_dev *dev = filp->private_data; + ssize_t ret = 0; -#if 0 - /* we will truncate hello_buffer */ - copy_from_user(dev->hello_buffer + *f_pos, buff, count); - return count; -#endif + if (down_interruptible(&dev->sem)) + return -ERESTARTSYS; - return 0; + if (count > HELLO_KERNEL_BUFF_LEN) + goto out; + + if (*f_pos + count > HELLO_KERNEL_BUFF_LEN) + count = HELLO_KERNEL_BUFF_LEN - *f_pos; + + if (copy_from_user(dev->hello_buffer + *f_pos, buff, count)) + { + ret = -EFAULT; + goto out; + } + ret = count; + + out: + up(&dev->sem); + return ret; } /* there's a count in filp that gets incremented every time our char device gets opened, but note that @@ -127,6 +172,7 @@ static int __init hello_init(void) } memset(hello_device, 0, sizeof(struct hello_dev)); hello_device->devnum = devnum; + sema_init(&hello_device->sem, 1); strcpy(hello_device->hello_buffer, "write to me\n"); /* setup char_dev structure */ diff --git a/main.h b/main.h index e437853..db38aa8 100644 --- a/main.h +++ b/main.h @@ -16,7 +16,9 @@ extern char *magicstr; struct hello_dev { dev_t devnum; + struct semaphore sem; struct cdev cdev; /* char device */ + /* for r/w operations */ char hello_buffer[HELLO_KERNEL_BUFF_LEN]; size_t buff_index; -- cgit v1.2.3