From c4abffb96e4ac41ee136d518ed2e8cad2a4cc819 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Sun, 6 Dec 2009 18:22:25 -0200 Subject: [PATCH 1/1] First character device. This version uses a kobject_put in an error path, which students may not know about yet. --- Makefile | 11 +++++++++ helloc.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 Makefile create mode 100644 helloc.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..76d1323 --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +ifneq ($(KERNELRELEASE),) + obj-m := helloc.o +else + KERNELDIR ?= /lib/modules/$(shell uname -r)/build + PWD := $(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules + +clean: + $(MAKE) -C $(KERNELDIR) M=$(PWD) clean +endif diff --git a/helloc.c b/helloc.c new file mode 100644 index 0000000..4d99fcb --- /dev/null +++ b/helloc.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Thadeu Lima de Souza Cascardo "); +MODULE_DESCRIPTION("A hello world char device"); +MODULE_VERSION("1.0.0"); + +static char helloc_message[] = "hello, world\n"; + +static ssize_t helloc_read(struct file *filp, char __user *buf, size_t len, + loff_t *pos) +{ + int r; + if (*pos >= sizeof(helloc_message)) + return 0; + if (len > sizeof(helloc_message) - *pos) + len = sizeof(helloc_message) - *pos; + r = copy_to_user(buf, helloc_message + *pos, len); + if (r) + return -EFAULT; + *pos += len; + return len; +} + +static struct file_operations helloc_fops = { + .owner = THIS_MODULE, + .read = helloc_read, +}; + +static dev_t dev; +static struct cdev *cdev; + +static int __init helloc_init(void) +{ + int r; + r = alloc_chrdev_region(&dev, 0, 1, "helloc"); + if (r) + goto out_region; + r = -ENOMEM; + printk(KERN_INFO "Allocated major number %d\n", MAJOR(dev)); + cdev = cdev_alloc(); + if (!cdev) + goto out_alloc; + cdev->owner = THIS_MODULE; + cdev->ops = &helloc_fops; + r = cdev_add(cdev, dev, 1); + if (r) + goto out_add; + return 0; +out_add: + kobject_put(&cdev->kobj); +out_alloc: + unregister_chrdev_region(dev, 1); +out_region: + return r; +} + +static void __exit helloc_exit(void) +{ + cdev_del(cdev); + unregister_chrdev_region(dev, 1); +} + +module_init(helloc_init); +module_exit(helloc_exit); -- 2.20.1