From 4035150ba08b34bbf43b91c822165a8d6cd5158e Mon Sep 17 00:00:00 2001 From: gatieme Date: Wed, 10 May 2017 23:56:02 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E6=A4=8D=E9=A9=B1=E5=8A=A8...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- books/21cnbao/code/08/globalfifo驱动/Makefile | 16 +- .../code/08/globalfifo驱动/globalfifo.c | 176 ++++++++++-------- .../code/08/poll应用程序范例/pollmonitor.c | 10 +- .../09/异步通知应用程序范例/asyncmonitor.c | 4 +- .../code/09/支持异步通知的globalfifo/Makefile | 75 ++++++++ .../globalfifo_async.c | 53 +++--- study/driver/00-code/hello/Makefile | 10 +- 7 files changed, 221 insertions(+), 123 deletions(-) create mode 100644 books/21cnbao/code/09/支持异步通知的globalfifo/Makefile diff --git a/books/21cnbao/code/08/globalfifo驱动/Makefile b/books/21cnbao/code/08/globalfifo驱动/Makefile index e505992..2427179 100644 --- a/books/21cnbao/code/08/globalfifo驱动/Makefile +++ b/books/21cnbao/code/08/globalfifo驱动/Makefile @@ -15,7 +15,7 @@ # my driver description DRIVER_VERSION := "1.0.0" -DRIVER_AUTHOR := "Gatieme @ AderStep Inc..." +DRIVER_AUTHOR := "globalfifo @ AderStep Inc..." DRIVER_DESC := "Linux input module for Elo MultiTouch(MT) devices" DRIVER_LICENSE := "Dual BSD/GPL" @@ -36,7 +36,7 @@ LINUX_KERNEL_PATH ?= /lib/modules/$(LINUX_KERNEL)/build CURRENT_PATH ?= $(shell pwd) CFG_INC = $(CURRENT_PATH) -MODCFLAGS:=-O2 -Wall -DMODULE -D__KERNEL__ -DLINUX -std=c99 +MODCFLAGS:=-O2 -Wall -DMODULE -D__KERNEL__ -DLINUX -std=gnu99 EXTRA_CFLAGS += $(MODULE_FLAGS) -I $(CFG_INC) @@ -47,20 +47,20 @@ modules_install: make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules_install insmod: - sudo insmod $(MODULE_NAME).ko globalmem_major=0 - sudo mknod /dev/gatieme c 242 0 - sudo chmod 666 /dev/gatieme + sudo insmod $(MODULE_NAME).ko globalfifo_major=0 + sudo mknod /dev/globalfifo c 242 0 + sudo chmod 666 /dev/globalfifo rmmod: sudo rmmod $(MODULE_NAME) - sudo rm -rf /dev/gatieme + sudo rm -rf /dev/globalfifo github: cd $(ROOT) && make github test : - echo "gatieme" > /dev/gatieme - cat /dev/gatieme + echo "gatieme" > /dev/globalfifo + cat /dev/globalfifo clean: make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean diff --git a/books/21cnbao/code/08/globalfifo驱动/globalfifo.c b/books/21cnbao/code/08/globalfifo驱动/globalfifo.c index 0247537..7ea332e 100644 --- a/books/21cnbao/code/08/globalfifo驱动/globalfifo.c +++ b/books/21cnbao/code/08/globalfifo驱动/globalfifo.c @@ -13,6 +13,9 @@ #include #include #include +#include +//#include + #include //#include @@ -21,9 +24,9 @@ #include #include -#define GLOBALFIFO_SIZE 0x1000 /* ȫfifo4Kֽ */ -#define FIFO_CLEAR 0x1 /* 0ȫڴij */ -#define GLOBALFIFO_MAJOR 253 /* Ԥglobalfifo豸 */ +#define GLOBALFIFO_SIZE 0x1000 /* ȫfifo4Kֽ */ +#define FIFO_CLEAR 0x1 /* 0ȫڴij */ +#define GLOBALFIFO_MAJOR 253 /* Ԥglobalfifo豸 */ static int globalfifo_major = GLOBALFIFO_MAJOR; @@ -55,6 +58,7 @@ int globalfifo_release(struct inode *inode, struct file *filp) return 0; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) /* ioctl豸ƺ */ static int globalfifo_ioctl( struct inode *inodep, @@ -62,6 +66,17 @@ static int globalfifo_ioctl( unsigned int cmd, unsigned long arg) { +#else +//long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); +//long (*compat_ioctl) (struct file *, unsigned int cmd, unsigned long arg) +static long globalfifo_unlocked_ioctl( + struct file *filp, + unsigned int cmd, + unsigned long arg) +{ + struct inode *inode = inode = file_inode(filp); +#endif + struct globalfifo_dev *dev = filp->private_data; /*豸ṹָ*/ switch (cmd) @@ -93,12 +108,12 @@ static unsigned int globalfifo_poll(struct file *filp, poll_table *wait) /*fifoǿ*/ if (dev->current_len != 0) { - mask |= POLLIN | POLLRDNORM; /*ʾݿɻ*/ + mask |= POLLIN | POLLRDNORM; /*ʾݿɻ*/ } /*fifo*/ if (dev->current_len != GLOBALFIFO_SIZE) { - mask |= POLLOUT | POLLWRNORM; /*ʾݿд*/ + mask |= POLLOUT | POLLWRNORM; /*ʾݿд*/ } up(&dev->sem); @@ -113,71 +128,69 @@ static ssize_t globalfifo_read( size_t count, loff_t *ppos) { - int ret; - struct globalfifo_dev *dev = filp->private_data; //豸ṹָ + int ret; + struct globalfifo_dev *dev = filp->private_data; //豸ṹָ - DECLARE_WAITQUEUE(wait, current); // ȴ + DECLARE_WAITQUEUE(wait, current); // ȴ - down(&dev->sem); // ź - add_wait_queue(&dev->r_wait, &wait); // ȴͷ + down(&dev->sem); // ź + add_wait_queue(&dev->r_wait, &wait); // ȴͷ - /* ȴFIFOǿ */ - if (dev->current_len == 0) - { - if (filp->f_flags &O_NONBLOCK) - { - ret = - EAGAIN; - goto out; - } + /* ȴFIFOǿ */ + if (dev->current_len == 0) + { + if (filp->f_flags &O_NONBLOCK) + { + ret = - EAGAIN; + goto out; + } - __set_current_state(TASK_INTERRUPTIBLE); //ı״̬Ϊ˯ + __set_current_state(TASK_INTERRUPTIBLE); //ı״̬Ϊ˯ - up(&dev->sem); + up(&dev->sem); + schedule( ); /* ִ */ - schedule(); //ִ + if (signal_pending(current)) /* ΪźŻ */ + { + ret = - ERESTARTSYS; + goto out2; + } - if (signal_pending(current)) - //ΪźŻ - { - ret = - ERESTARTSYS; - goto out2; - } + down(&dev->sem); + } - down(&dev->sem); - } + /* ûռ */ + if (count > dev->current_len) + { + count = dev->current_len; + } - /* ûռ */ - if (count > dev->current_len) - { - count = dev->current_len; - } + if (copy_to_user(buf, dev->mem, count)) + { + ret = - EFAULT; + goto out; + } + else + { + memcpy(dev->mem, dev->mem + count, dev->current_len - count); //fifoǰ + dev->current_len -= count; //Чݳȼ + printk(KERN_INFO "read %d bytes(s),current_len:%d\n", count, dev->current_len); - if (copy_to_user(buf, dev->mem, count)) - { - ret = - EFAULT; - goto out; - } - else - { - memcpy(dev->mem, dev->mem + count, dev->current_len - count); //fifoǰ - dev->current_len -= count; //Чݳȼ - printk(KERN_INFO "read %d bytes(s),current_len:%d\n", count, dev->current_len); + wake_up_interruptible(&dev->w_wait); //дȴ - wake_up_interruptible(&dev->w_wait); //дȴ - - ret = count; + ret = count; } out : - up(&dev->sem); //ͷź + up(&dev->sem); //ͷź out2 : - remove_wait_queue(&dev->w_wait, &wait); //ӸĵȴͷƳ - set_current_state(TASK_RUNNING); + remove_wait_queue(&dev->w_wait, &wait); //ӸĵȴͷƳ + set_current_state(TASK_RUNNING); - return ret; + return ret; } @@ -195,49 +208,52 @@ static ssize_t globalfifo_write(struct file *filp, const char __user *buf, /* ȴFIFO */ if (dev->current_len == GLOBALFIFO_SIZE) { - if (filp->f_flags &O_NONBLOCK) - //Ƿ - { - ret = - EAGAIN; - goto out; - } - __set_current_state(TASK_INTERRUPTIBLE); //ı״̬Ϊ˯ - up(&dev->sem); + if (filp->f_flags &O_NONBLOCK) + //Ƿ + { + ret = - EAGAIN; + goto out; + } + __set_current_state(TASK_INTERRUPTIBLE); //ı״̬Ϊ˯ + up(&dev->sem); - schedule(); //ִ - if (signal_pending(current)) - //ΪźŻ - { - ret = - ERESTARTSYS; - goto out2; - } + schedule(); /* ִ */ + if (signal_pending(current)) /* ΪźŻ */ + { + ret = - ERESTARTSYS; + goto out2; + } - down(&dev->sem); //ź + down(&dev->sem); //ź } /*ûռ俽ں˿ռ*/ if (count > GLOBALFIFO_SIZE - dev->current_len) - count = GLOBALFIFO_SIZE - dev->current_len; + count = GLOBALFIFO_SIZE - dev->current_len; if (copy_from_user(dev->mem + dev->current_len, buf, count)) { - ret = - EFAULT; - goto out; + ret = - EFAULT; + goto out; } else { - dev->current_len += count; - printk(KERN_INFO "written %d bytes(s),current_len:%d\n", count, dev - ->current_len); + dev->current_len += count; + printk(KERN_INFO "written %d bytes(s),current_len:%d\n", + count, dev->current_len); - wake_up_interruptible(&dev->r_wait); //Ѷȴ + wake_up_interruptible(&dev->r_wait); //Ѷȴ - ret = count; + ret = count; } - out: up(&dev->sem); //ͷź - out2:remove_wait_queue(&dev->w_wait, &wait); //ӸĵȴͷƳ +out: + up(&dev->sem); //ͷź + +out2: + remove_wait_queue(&dev->w_wait, &wait); //ӸĵȴͷƳ set_current_state(TASK_RUNNING); + return ret; } @@ -248,7 +264,11 @@ static const struct file_operations globalfifo_fops = .owner = THIS_MODULE, .read = globalfifo_read, .write = globalfifo_write, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) .ioctl = globalfifo_ioctl, +#else + .unlocked_ioctl = globalfifo_unlocked_ioctl, +#endif .poll = globalfifo_poll, .open = globalfifo_open, .release = globalfifo_release, @@ -295,7 +315,7 @@ int globalfifo_init(void) globalfifo_setup_cdev(globalfifo_devp, 0); #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36) && !defined(init_MUTEX) - sema_init(&sem, 1); + sema_init(&globalfifo_devp->sem, 1); #else init_MUTEX(&globalfifo_devp->sem); /*ʼź*/ #endif diff --git a/books/21cnbao/code/08/poll应用程序范例/pollmonitor.c b/books/21cnbao/code/08/poll应用程序范例/pollmonitor.c index b8c41e6..aec07d5 100644 --- a/books/21cnbao/code/08/poll应用程序范例/pollmonitor.c +++ b/books/21cnbao/code/08/poll应用程序范例/pollmonitor.c @@ -1,8 +1,8 @@ /*====================================================================== - A test program in userspace + A test program in userspace This example is to introduce the ways to use "select" - and driver poll - + and driver poll + The initial developer of the original code is Baohua Song . All Rights Reserved. ======================================================================*/ @@ -20,7 +20,7 @@ main() int fd, num; char rd_ch[BUFFER_LEN]; fd_set rfds,wfds; - + /*Էʽ/dev/globalmem豸ļ*/ fd = open("/dev/globalfifo", O_RDONLY | O_NONBLOCK); if (fd != - 1) @@ -47,7 +47,7 @@ main() if (FD_ISSET(fd, &wfds)) { printf("Poll monitor:can be written\n"); - } + } } } else diff --git a/books/21cnbao/code/09/异步通知应用程序范例/asyncmonitor.c b/books/21cnbao/code/09/异步通知应用程序范例/asyncmonitor.c index 0a7c663..c4cbacd 100644 --- a/books/21cnbao/code/09/异步通知应用程序范例/asyncmonitor.c +++ b/books/21cnbao/code/09/异步通知应用程序范例/asyncmonitor.c @@ -1,7 +1,7 @@ /*====================================================================== A test program to access /dev/second - This example is to help understand async IO - + This example is to help understand async IO + The initial developer of the original code is Baohua Song . All Rights Reserved. ======================================================================*/ diff --git a/books/21cnbao/code/09/支持异步通知的globalfifo/Makefile b/books/21cnbao/code/09/支持异步通知的globalfifo/Makefile new file mode 100644 index 0000000..d9f4616 --- /dev/null +++ b/books/21cnbao/code/09/支持异步通知的globalfifo/Makefile @@ -0,0 +1,75 @@ +# ------------------------------------------------------------------------------ +# +# Makefile for the LDD-LinuxDeviceDrivers. +# +# Author: gatieme +# Create: 2016-07-29 15:50:46 +# Last modified: 2016-07-29 16:10:29 +# Description: +# This program is loaded as a kernel(v2.6.18 or later) module. +# Use "make install" to load it into kernel. +# Use "make remove" to remove the module out of kernel. +# +# ------------------------------------------------------------------------------ + + +# my driver description +DRIVER_VERSION := "1.0.0" +DRIVER_AUTHOR := "globalfifo @ AderStep Inc..." +DRIVER_DESC := "Linux input module for Elo MultiTouch(MT) devices" +DRIVER_LICENSE := "Dual BSD/GPL" + + +MODULE_NAME := globalfifo_async + + + +ifneq ($(KERNELRELEASE),) # kernelspace + +obj-m := $(MODULE_NAME).o + +else # userspace + + +LINUX_KERNEL ?= $(shell uname -r) +LINUX_KERNEL_PATH ?= /lib/modules/$(LINUX_KERNEL)/build + +CURRENT_PATH ?= $(shell pwd) +CFG_INC = $(CURRENT_PATH) +MODCFLAGS:=-O2 -Wall -DMODULE -D__KERNEL__ -DLINUX -std=gnu99 +EXTRA_CFLAGS += $(MODULE_FLAGS) -I $(CFG_INC) + + +modules: + make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules + +modules_install: + make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules_install + +insmod: + sudo insmod $(MODULE_NAME).ko globalfifo_major=0 + sudo mknod /dev/globalfifo c 242 0 + sudo chmod 666 /dev/globalfifo + +rmmod: + sudo rmmod $(MODULE_NAME) + sudo rm -rf /dev/globalfifo + +github: + cd $(ROOT) && make github + +test : + echo "gatieme" > /dev/globalfifo + cat /dev/globalfifo + +clean: + make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean + rm -f modules.order Module.symvers Module.markers + +.PHNOY: + modules modules_install clean + + + +endif + diff --git a/books/21cnbao/code/09/支持异步通知的globalfifo/globalfifo_async.c b/books/21cnbao/code/09/支持异步通知的globalfifo/globalfifo_async.c index 93d3510..8d6bf8c 100644 --- a/books/21cnbao/code/09/支持异步通知的globalfifo/globalfifo_async.c +++ b/books/21cnbao/code/09/支持异步通知的globalfifo/globalfifo_async.c @@ -1,7 +1,7 @@ /*====================================================================== - A globalfifo driver as an example of char device drivers + A globalfifo driver as an example of char device drivers This example is to introduce asynchronous notifier - + The initial developer of the original code is Baohua Song . All Rights Reserved. ======================================================================*/ @@ -14,7 +14,10 @@ #include #include #include -#include + +//#include +#include + #include #include @@ -24,15 +27,15 @@ static int globalfifo_major = GLOBALFIFO_MAJOR; /*globalfifo豸ṹ*/ -struct globalfifo_dev -{ - struct cdev cdev; /*cdevṹ*/ +struct globalfifo_dev +{ + struct cdev cdev; /*cdevṹ*/ unsigned int current_len; /*fifoЧݳ*/ - unsigned char mem[GLOBALFIFO_SIZE]; /*ȫڴ*/ - struct semaphore sem; /*õź*/ - wait_queue_head_t r_wait; /*õĵȴͷ*/ - wait_queue_head_t w_wait; /*дõĵȴͷ*/ - struct fasync_struct *async_queue; /* 첽ṹָ룬ڶ */ + unsigned char mem[GLOBALFIFO_SIZE]; /*ȫڴ*/ + struct semaphore sem; /*õź*/ + wait_queue_head_t r_wait; /*õĵȴͷ*/ + wait_queue_head_t w_wait; /*дõĵȴͷ*/ + struct fasync_struct *async_queue; /* 첽ṹָ룬ڶ */ }; struct globalfifo_dev *globalfifo_devp; /*豸ṹָ*/ @@ -48,7 +51,7 @@ int globalfifo_release(struct inode *inode, struct file *filp) { /* ļ첽֪ͨбɾ */ globalmem_fasync( - 1, filp, 0); - + return 0; } @@ -61,12 +64,12 @@ static int globalfifo_ioctl(struct inode *inodep, struct file *filp, unsigned switch (cmd) { case FIFO_CLEAR: - down(&dev->sem); //ź + down(&dev->sem); //ź dev->current_len = 0; memset(dev->mem,0,GLOBALFIFO_SIZE); up(&dev->sem); //ͷź - - printk(KERN_INFO "globalfifo is set to zero\n"); + + printk(KERN_INFO "globalfifo is set to zero\n"); break; default: @@ -79,11 +82,11 @@ static unsigned int globalfifo_poll(struct file *filp, poll_table *wait) { unsigned int mask = 0; struct globalfifo_dev *dev = filp->private_data; /*豸ṹָ*/ - + down(&dev->sem); - + poll_wait(filp, &dev->r_wait, wait); - poll_wait(filp, &dev->w_wait, wait); + poll_wait(filp, &dev->w_wait, wait); /*fifoǿ*/ if (dev->current_len != 0) { @@ -94,7 +97,7 @@ static unsigned int globalfifo_poll(struct file *filp, poll_table *wait) { mask |= POLLOUT | POLLWRNORM; /*ʾݿд*/ } - + up(&dev->sem); return mask; } @@ -102,7 +105,7 @@ static unsigned int globalfifo_poll(struct file *filp, poll_table *wait) /* globalfifo fasync*/ static int globalfifo_fasync(int fd, struct file *filp, int mode) { - struct globalfifo_dev *dev = filp->private_data; + struct globalfifo_dev *dev = filp->private_data; return fasync_helper(fd, filp, mode, &dev->async_queue); } @@ -125,7 +128,7 @@ static ssize_t globalfifo_read(struct file *filp, char __user *buf, size_t count { ret = - EAGAIN; goto out; - } + } __set_current_state(TASK_INTERRUPTIBLE); //ı״̬Ϊ˯ up(&dev->sem); @@ -154,9 +157,9 @@ static ssize_t globalfifo_read(struct file *filp, char __user *buf, size_t count memcpy(dev->mem, dev->mem + count, dev->current_len - count); //fifoǰ dev->current_len -= count; //Чݳȼ printk(KERN_INFO "read %d bytes(s),current_len:%d\n", count, dev->current_len); - + wake_up_interruptible(&dev->w_wait); //дȴ - + ret = count; } out: up(&dev->sem); //ͷź @@ -185,7 +188,7 @@ static ssize_t globalfifo_write(struct file *filp, const char __user *buf, { ret = - EAGAIN; goto out; - } + } __set_current_state(TASK_INTERRUPTIBLE); //ı״̬Ϊ˯ up(&dev->sem); @@ -219,7 +222,7 @@ static ssize_t globalfifo_write(struct file *filp, const char __user *buf, /* 첽ź */ if (dev->async_queue) kill_fasync(&dev->async_queue, SIGIO, POLL_IN); - + ret = count; } diff --git a/study/driver/00-code/hello/Makefile b/study/driver/00-code/hello/Makefile index 180084b..5ffdb3f 100644 --- a/study/driver/00-code/hello/Makefile +++ b/study/driver/00-code/hello/Makefile @@ -31,12 +31,12 @@ obj-m := $(MODULE_NAME).o else # userspace -LINUX_KERNEL ?= $(shell uname -r) -LINUX_KERNEL_PATH ?= /lib/modules/$(LINUX_KERNEL)/build +LINUX_KERNEL := $(shell uname -r) +LINUX_KERNEL_PATH := /lib/modules/$(LINUX_KERNEL)/build -CURRENT_PATH ?= $(shell pwd) -CFG_INC = $(CURRENT_PATH) -MODCFLAGS:=-O2 -Wall -DMODULE -D__KERNEL__ -DLINUX -std=c99 +CURRENT_PATH := $(shell pwd) +CFG_INC := $(CURRENT_PATH) +MODCFLAGS := -O2 -Wall -DMODULE -D__KERNEL__ -DLINUX -std=c99 EXTRA_CFLAGS += $(MODULE_FLAGS) -I $(CFG_INC)