China embedded-memdev device for Linux character device driver Learning

Source: Internet
Author: User

Memdev device driver source code

Memdev. h. Custom header file ************************************ **************************************** ** # ifndef _ memdev_h _ # DEFINE _ memdev_h _ # ifndef memdev_major # define memdev_major 254/* default mem primary device Number */# endif # ifndef primary # define limit 2 /* number of devices */# endif # ifndef memdev_size # define memdev_size 4096 // size of memory allocated # endif/* mem device description struct */struct mem_dev {char * data; // The initial address unsigned Long size of the allocated memory; // memory size}; # endif/* _ memdev_h _*/
Memdev. c. A complete character driver ********************************* **************************************** * ***** # include <Linux/module. h> # include <Linux/types. h> # include <Linux/Fs. h> # include <Linux/errno. h> # include <Linux/mm. h> # include <Linux/sched. h> # include <Linux/init. h> # include <Linux/cdev. h> # include <ASM/Io. h> # include <ASM/system. h> # include <ASM/uaccess. h> # include "memdev. H "static mem_major = memdev_major; Module_param (mem_major, Int, s_irugo); struct mem_dev * mem_devp;/* Device struct pointer */struct cdev;/* file open function */INT mem_open (struct inode * inode, struct file * filp) {struct mem_dev * dev;/* get the device Number */INT num = minor (inode-> I _rdev ); // inode-> I _rdev contains the actual device number if (Num> = memdev_nr_devs) Return-enodev; Dev = & mem_devp [num]; /* assign the device description structure pointer to the file Private Data Pointer */filp-> private_data = dev; // use this member to point to the allocated data return 0 ;} /* file release function */I NT mem_release (struct inode * inode, struct file * filp) {return 0;}/* read function */static ssize_t mem_read (struct file * filp, char _ User * Buf, size_t size, loff_t * PPOs) // Buf cache, size Read File Size, PPOs current read/write location {unsigned long P = * PPOs; // P indicates the current read/write position unsigned int COUNT = size; // the size of one read int ret = 0; struct mem_dev * Dev = filp-> private_data; /* get the device struct pointer * // * determine whether the read location is valid */If (P> = memdev_size) // determine whether the read location exceeds the value of returned 0; If (count> Memdev_size-p) Count = memdev_size-P; // if the value of count is greater than the readable range, the read range is reduced. /* Read data to user space */If (copy_to_user (BUF, (void *) (Dev-> Data + p), count) // return Buf, read location, read count {ret =-efault;} else {* PPOs + = count; // Move the current position of the file back to ret = count; // returns the actual number of bytes read printk (kern_info "read % d bytes (s) from % d \ n", Count, P);} return ret; // return the actual number of bytes read to determine whether the read is successful}/* write function */static ssize_t mem_write (struct file * filp, const char _ User * Buf, size_t size, loff_t * PPOs) // write is similar to read. For more information, see read {unsigned long P = * PPOs; unsigned int COUNT = size; int ret = 0; struct mem_dev * Dev = filp-> private_data; /* get the device struct pointer * // * analyze and obtain valid write lengths */If (P> = memdev_size) return 0; If (count> memdev_size-P) count = memdev_size-P;/* write data from user space */If (copy_from_user (Dev-> Data + P, Buf, count) ret =-efault; else {* PPOs + = count; ret = count; printk (kern_info "written % d bytes (s) from % d \ n", Count, P);} return ret ;} /* seek text Location function */static loff_t mem_llseek (struct file * filp, loff_t offset, int whence) // Changes the current read/write position in the file, and the new position is (positive) the returned value must be located again in the test program. Whence is set to seek_set {loff_t newpos here; Switch (whence) {Case 0:/* seek_set */newpos = offset; // locate break from the file header; Case 1:/* seek_cur */newpos = filp-> f_pos + offset; // locate break from the file center; Case 2: /* seek_end */newpos = memdev_size-1 + offset; // start from the end of the file. Because the position starts from 0, 1 break is required. DEFA Ult:/* can't happen */Return-einval;} If (newpos <0) | (newpos> memdev_size) Return-einval; filp-> f_pos = newpos; // return the current file location return newpos;}/* file operation struct */static const struct file_operations mem_fops = {. owner = this_module ,. llseek = mem_llseek ,. read = mem_read ,. write = mem_write ,. open = mem_open ,. release = mem_release,};/* Device Driver Module Loading Function */static int memdev_init (void) // initialization module {int result; int I; Dev_t devno = mkdev (mem_major, 0); // mkdev converts the master and secondary device numbers into dev_t data, the mem_major parameter is set to 254/* apply for the device ID statically */If (mem_major)/memdev in the header file. the value of H is 254. Therefore, in this example, the master device number 254 result = register_chrdev_region (devno, 2, "memdev") is allocated statically. // devno is the master device number. Two consecutive devices are requested, the device name is "memdev" else/* dynamically allocates the device Number */{result = alloc_chrdev_region (& devno, 0, 2, "memdev"); // & devno is used as an output parameter, the device number starts from 0 and applies for two devices. The device name is "memdev" mem_major = major (devno); // gets the dynamically assigned master device number.} If (result <0) // If the returned result is 0, the application is successful, and the negative value of the backend is failed. Return result;/* initialize the cdev structure */cdev_init (& cdev, & mem_fops); // initialize the cdev structure and bind the cdev and mem_fops struct to the cdev. owner = this_module; // The reference count of the driver. This is used when the driver is in use. When you use the inmod command again, a warning message is displayed, prompting cdev. ops = & mem_fops;/* register a character device */cdev_add (& cdev, mkdev (mem_major, 0), memdev_nr_devs); // memdev_nr_devs = 2, allocate 2 devices/* allocate memory for the device description structure */mem_devp = kmalloc (memdev_nr_devs * sizeof (struct mem_dev), gfp_kernel ); // The kmalloc function returns a virtual address (linear address ). if (! Mem_devp)/* application failed */{result =-enomem; goto fail_malloc;} memset (mem_devp, 0, sizeof (struct mem_dev )); // initialize the newly applied memory/* allocate memory to the device */for (I = 0; I <memdev_nr_devs; I ++) {mem_devp [I]. size = memdev_size; // # define memdev_size 4096 mem_devp [I]. data = kmalloc (memdev_size, gfp_kernel); // allocate memory to two devices: memset (mem_devp [I]. data, 0, memdev_size); // initialize the newly allocated memory} return 0; fail_malloc: unregister_chrdev_region (devno, 1); // if the application fails, log out of the device and return result ;} /* module unmount function */static void memdev_exit (void) {cdev_del (& cdev);/* log out of the device */kfree (mem_devp ); /* release the device struct memory */unregister_chrdev_region (mkdev (mem_major, 0), 2);/* release the device Number */} module_author ("David xie "); module_license ("GPL"); module_init (memdev_init); module_exit (memdev_exit );

Test. C testing program ************************************* **************************************** ** # include <stdio. h> int main () {file * fp0 = NULL; char Buf [4096];/* initialize Buf */strcpy (BUF, "mem is Char Dev! "); Printf (" Buf: % s \ n ", Buf);/* Open the device file */fp0 = fopen ("/dev/memdev0 ", "R +"); If (fp0 = NULL) {printf ("Open memdev0 error! \ N "); Return-1;}/* Write Device */fwrite (BUF, sizeof (BUF), 1, fp0 ); /* relocate the file location (think about the consequences of not having this command) */fseek (fp0, 0, seek_set); // call mem_llseek () to locate, move the file pointer back to the starting position to facilitate reading/* clearing Buf */strcpy (BUF, "Buf is null! "); // Overwrite the previous value to prevent printf (" Buf: % s \ n ", Buf) from being judged when the data cannot be read ); /* read the device */fread (BUF, sizeof (BUF), 1, fp0);/* test result */printf ("Buf: % s \ n", Buf ); return 0 ;}

 

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.