Sample Code of "Linux device driver development details" by Song Baohua: FIFO Device Driver

Source: Internet
Author: User

The driver code is as follows:

Scull. c

#include <linux/fs.h>#include <linux/kernel.h>#include <linux/cdev.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/gfp.h>#include <linux/poll.h>#include <asm/uaccess.h>#defineSCULL_MAJOR252#define SCULL_NAME"scull"#define MAX_DATA0x10staticint scull_major = SCULL_MAJOR;struct scull_dev {struct cdev cdev;unsigned char data[MAX_DATA];struct semaphore sem;unsigned int current_len;wait_queue_head_t r_wait;wait_queue_head_t w_wait;};MODULE_LICENSE("GPL");MODULE_AUTHOR("BG2BKK");structscull_dev *scull_devp;intscull_open(struct inode *inode, struct file *filp){struct scull_dev *dev = container_of(inode->i_cdev, struct scull_dev, cdev);filp->private_data = dev;printk(KERN_ALERT "open the scull device\n");return 0;}intscull_release(struct inode *inode, struct file *filp){printk(KERN_ALERT "close the scull device\n");return 0;}ssize_tscull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_ops){struct scull_dev *dev = filp->private_data;int ret = 0;DECLARE_WAITQUEUE(wait, current);down(&dev->sem);add_wait_queue(&dev->r_wait, &wait);while(dev->current_len == 0){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;}down(&dev->sem);}if(count > dev->current_len)count = dev->current_len;if(copy_to_user(buf, dev->data,count)){ret = -EFAULT;goto out;} else {memcpy(dev->data, dev->data + count, dev->current_len - count);dev->current_len -= count;printk(KERN_ALERT "read %u bytes; current_len:%d\n",count, dev->current_len);wake_up_interruptible(&dev->w_wait);ret = count;}out:up(&dev->sem);out2:remove_wait_queue(&dev->w_wait, &wait);set_current_state(TASK_RUNNING);return ret;}ssize_t scull_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_ops){struct scull_dev *dev = filp->private_data;int ret = 0;DECLARE_WAITQUEUE(wait, current);down(&dev->sem);add_wait_queue(&dev->w_wait, &wait);while(dev->current_len == MAX_DATA){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;}down(&dev->sem);}if(count > MAX_DATA - dev->current_len){count = MAX_DATA - dev->current_len;}if(copy_from_user(dev->data + dev->current_len, buf, count)){ret = -EFAULT;goto out;}else {dev->current_len += count;printk(KERN_ALERT "written %d bytes, current_len:%d\n",count, dev->current_len);wake_up_interruptible(&dev->r_wait);ret = count;}out:up(&dev->sem);out2:remove_wait_queue(&dev->w_wait, &wait);set_current_state(TASK_RUNNING);return ret;}staticunsigned int scull_poll(struct file *filp, poll_table *wait){unsigned int mask = 0;struct scull_dev *dev = filp->private_data;down(&dev->sem);poll_wait(filp, &dev->r_wait, wait);poll_wait(filp, &dev->w_wait, wait);if(dev->current_len != 0)mask |= POLLIN | POLLRDNORM;if(dev->current_len != MAX_DATA)mask |= POLLOUT | POLLWRNORM;up(&dev->sem);return mask;}static const structfile_operations scull_fops = {.owner=THIS_MODULE,.open=scull_open,.release=scull_release,.write=scull_write,.read=scull_read,.poll=scull_poll,};staticvoidscull_setup_cdev(struct scull_dev *dev, int index){int err, devno = MKDEV(scull_major, index);cdev_init(&dev->cdev, &scull_fops);dev->cdev.owner = THIS_MODULE;err = cdev_add(&dev->cdev, devno, 1);if(err)printk(KERN_NOTICE "ERROR %d adding scull_dev %d", err, index);}intscull_init(void){int result;dev_tdevno = MKDEV(scull_major,0);if(scull_major)result = register_chrdev_region(devno, 1, "scull");else {result = alloc_chrdev_region(&devno, 0, 1, "scull");scull_major = MAJOR(devno);}if(result < 0)return result;scull_devp = kmalloc(sizeof(struct scull_dev), GFP_KERNEL);if(!scull_devp){result = -ENOMEM;goto fail_malloc;}memset(scull_devp, 0 , sizeof(struct scull_dev));scull_setup_cdev(scull_devp, 0);init_MUTEX(&scull_devp->sem);init_waitqueue_head(&scull_devp->r_wait);init_waitqueue_head(&scull_devp->w_wait);printk(KERN_ALERT "init scull device\n");return 0;fail_malloc:unregister_chrdev_region(devno, 1);return result;}voidscull_cleanup(void){cdev_del(&scull_devp->cdev);kfree(scull_devp);unregister_chrdev_region(MKDEV(scull_major, 0), 1);printk(KERN_ALERT "clean scull device\n");}module_init(scull_init);module_exit(scull_cleanup);

Test code

/************************************************************************* *fileName:    test.c *description: test the myscull.c *author:      Hzc *create time: 2007-04-20 *modify info: -*************************************************************************/#include <stdio.h>#include <fcntl.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/time.h>#define BUFFER_LEN 20#define FIFO_CLEAR 0x01#define device"/dev/scull"int main(){int num;fd_set rfds, wfds;int fd = open(device, O_RDONLY| O_NONBLOCK);if(fd != 0){while(1){FD_ZERO(&rfds);FD_ZERO(&wfds);FD_SET(fd, &rfds);FD_SET(fd, &wfds);select(fd+1, &rfds, &wfds, NULL, NULL);if(FD_ISSET(fd, &rfds))printf("poll monitor: can be read\n");if(FD_ISSET(fd, &wfds))printf("poll monitor: can be written\n");}} else{printf("Device " device "open failer");}}

Makefile

KERNEL_DIR := /lib/modules/$(shell uname -r)/buildPWD:= $(shell pwd)obj-m := scull.odefault:$(MAKE) -C $(KERNEL_DIR) SUBDIRS=$(PWD) modulestest: test.cgcc $< -o $@.o  -gclean:rm -rf *.o *.ko *~ *.order *.symvers *.markers *.mod.c

Test script

1 load_scull.sh

#!/bin/sh/sbin/insmod scull.komknod /dev/scull c 252 0

2 unload_scull.sh

#!/bin/sh/sbin/rmmod scull.korm /dev/scull -f

3 test. Sh

#!/bin/shmake cleanmake make testsudo ./unload_scullsudo ./load_scullsudo ./test.o

Run./test. O during the test. The terminal always outputs poll monitor: Can be write,

On another terminal, in the root user mode, Echo Hello>/dev/scull, you can see the output poll monitor: can be read and poll monitor: Can be write

After multiple echo Hello>/dev/scull times, because the scull device buffer is only 16B, it can no longer be written. At this time, only the poll monitor: can be read is output.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.