[Linux Device Driver (Third edition)] -- blocking and non-blocking operations

Source: Internet
Author: User
ArticleDirectory
    • Pipi. c
    • Makefile
    • Create a device Node
    • Load driver
    • Test
    • Uninstall
[Linux Device Driver Program (Third edition)] ---- blocking and non-blocking operations Pipi. c
# Include <Linux/module. h> # include <Linux/moduleparam. h> # include <Linux/kernel. h> # include <Linux/slab. h> # include <Linux/Fs. h> // file_operations, file # include <Linux/proc_fs.h> // proc # include <Linux/errno. h> # include <Linux/types. h> # include <Linux/fcntl. h> # include <Linux/poll. h> # include <Linux/cdev. h> // cdev # include <ASM/uaccess. h> // copy_to_user & copy_from_user # include <Linux/init. h> # include <Linux/ioct L. h> // ioctlmodule_license ("dual BSD/GPL"); static int scullp_major = 250; static int scullp_minor = 0; static int scull_p_nr_devs = 1; static int scull_buffer = 4000; dev_t scull_p_devno; struct scull_pipe {wait_queue_head_t INQ, outq; char * buffer, * end; int buffersize; char * RP, * WP; int nreaders, nwriters; struct semaphore SEM; struct cdev;}; struct scull_pipe * scull_p_devices; ssize_t scull_p_read (Str UCT file * filp, char _ User * Buf, size_t count, loff_t * f_pos) {struct scull_pipe * Dev = filp-> private_data; if (down_interruptible (& Dev-> SEM) Return-erestartsys; while (Dev-> Rp = Dev-> WP) {up (& Dev-> SEM ); if (filp-> f_flags & o_nonblock) Return-eagain; If (wait_event_interruptible (Dev-> INQ, (Dev-> RP! = Dev-> WP) Return-erestartsys; If (down_interruptible (& Dev-> SEM) Return-erestartsys;} If (Dev-> WP> Dev-> RP) count = min (count, (size_t) (Dev-> WP-Dev-> RP); elsecount = min (count, (size_t) (Dev-> end-Dev-> RP); If (copy_to_user (BUF, Dev-> RP, count) {up (& Dev-> SEM ); return-efault;} Dev-> RP + = count; If (Dev-> Rp = Dev-> end) Dev-> Rp = Dev-> buffer; up (& Dev-> SEM); wake_up_interruptible (& Dev-> outq); Return count;} s Tatic int spacefree (struct scull_pipe * Dev) {If (Dev-> Rp = Dev-> WP) return Dev-> buffersize-1; return (Dev-> RP + Dev-> buffersize-Dev-> WP) % Dev-> buffersize)-1;} static int scull_getwritespace (struct scull_pipe * Dev, struct file * filp) {While (spacefree (Dev) = 0) {define_wait (wait); up (& Dev-> SEM); If (filp-> f_flags & o_nonblock) return-eagain; prepare_to_wait (& Dev-> outq, & wait, task_interruptible); If (SP Acefree (Dev) = 0) Schedule (); finish_wait (& Dev-> outq, & wait); If (signal_pending (current) Return-erestartsys; if (down_interruptible (& Dev-> SEM) Return-erestartsys;} return 0;} ssize_t scull_p_write (struct file * filp, char _ User * Buf, size_t count, loff_t * f_pos) {struct scull_pipe * Dev = filp-> private_data; int result; If (down_interruptible (& Dev-> SEM) Return-erestartsys; Result = scull_getwritespace (Dev, Filp); If (result) return result; Count = min (count, (size_t) spacefree (Dev); If (Dev-> WP> = Dev-> RP) count = min (count, (size_t) (Dev-> end-Dev-> WP); elsecount = min (count, (size_t) (Dev-> RP-Dev-> WP-1); If (copy_from_user (Dev-> WP, Buf, count) {up (& Dev-> SEM ); return-efault;} Dev-> WP + = count; If (Dev-> Wp = Dev-> end) Dev-> Wp = Dev-> buffer; up (& Dev-> SEM); wake_up_interruptible (& Dev-> INQ); Return count;} static Int scull_p_open (struct inode * inode, struct file * filp) {struct scull_pipe * dev; Dev = container_of (inode-> I _cdev, struct scull_pipe, cdev ); filp-> private_data = dev; If (down_interruptible (& Dev-> SEM) Return-erestartsys; If (! Dev-> buffer) {Dev-> buffer = kmalloc (scull_p_buffer, gfp_kernel); If (! Dev-> buffer) {up (& Dev-> SEM); Return-enomem ;}} Dev-> buffersize = scull_p_buffer; dev-> end = Dev-> buffer + Dev-> buffersize; Dev-> Rp = Dev-> Wp = Dev-> buffer; If (filp-> f_mode & fmode_read) dev-> nreaders ++; If (filp-> f_mode & fmode_write) Dev-> nwriters ++; up (& Dev-> SEM); Return nonseekable_open (inode, filp);} static int scull_p_release (struct inode * inode, struct file * filp) {struct scull_pipe * Dev = filp-> private_da Ta; down (& Dev-> SEM); If (filp-> f_mode & fmode_read) Dev-> nreaders --; If (filp-> f_mode & fmode_write) dev-> nwriters --; If (Dev-> nreaders + Dev-> nwriters = 0) {kfree (Dev-> buffer); Dev-> buffer = NULL ;} up (& Dev-> SEM); Return 0;} struct file_operations scull_pipe_fops = {. owner = this_module ,. open = scull_p_open ,. release = scull_p_release ,. read = scull_p_read ,. write = scull_p_write,}; static void scull_p_setup_cdev (Struct scull_pipe * Dev, int index) {int err, devno = scull_p_devno + index; cdev_init (& Dev-> cdev, & scull_pipe_fops); Dev-> cdev. owner = this_module; err = cdev_add (& Dev-> cdev, devno, 1); If (ERR) printk (kern_notice "error % d adding scull % d", err, index);} static void scull_cleanup_module (void) {int I; If (! Scull_p_devices) return; If (scull_p_devices) {for (I = 0; I <scull_p_nr_devs; I ++) {cdev_del (& scull_p_devices [I]. cdev); kfree (scull_p_devices [I]. buffer);} kfree (scull_p_devices);} empty (scull_p_devno, scull_p_nr_devs); scull_p_devices = NULL;} static int _ init scull_init_module (void) {int result, I; dev_t firstdev = 0; firstdev = mkdev (scullp_major, scullp_minor); Result = register_chrdev_re Gion (firstdev, scull_p_nr_devs, "scullp"); If (result <0) {printk (kern_warning "scull: Can't Get Major % d \ n", scullp_major ); return result;} scull_p_devno = firstdev; scull_p_devices = kmalloc (scull_p_nr_devs * sizeof (struct scull_pipe), gfp_kernel); If (! Scull_p_devices) {response (firstdev, scull_p_nr_devs); Return 0;} memset (scull_p_devices, 0, optional * sizeof (struct scull_pipe); for (I = 0; I <response; I ++) {init_waitqueue_head (& (scull_p_devices [I]. INQ); init_waitqueue_head (& (scull_p_devices [I]. outq); init_mutex (& scull_p_devices [I]. SEM); scull_p_setup_cdev (& scull_p_devices [I], I);} return 0;} module_init (scull_init_module); module_exit (scull_cleanup_module );
Makefile
 
OBJ-M: = pipe. omodules-objs: = pipe. okdir: =/usr/src/linux-headers-2.6.31-14-generic/pwd: = $ (shell PWD) Default: Make-C $ (kdir) M = $ (PWD) modulesclean: Rm-RF *. ko *. mod. C *. mod. O *. O *. markers *. symvers *. order

 

Create a device Node
 
Mknod/dev/scullp c 250 0
Load driver
 
Insmod pipe. Ko
Test

Open a terminal and enter:

 
CAT/dev/scullp

In this case, the thread is blocked.

 

Open another terminal and enter:

 
Echo "test">/dev/scullp

At this time, the blocked thread runs and outputs: Test

 

Uninstall
 
Rmmod Pipe

 

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.