A simple example of a Linux character Device Driver

Source: Internet
Author: User

I. Development Environment:

MASTER: VMWare -- fedora 9

Development Board: friendly arm mini2440 -- 256 MB nandflash

Compiler: Arm-Linux-gcc- 4.3.2

 

Ii. driver source code:

The source code is easy to understand and suitable for beginners.

Memdev. h

# 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 # endif/* mem device description struct */struct mem_dev {char * data; unsigned Long SIZE ;};# endif/* _ memdev_h _*/

Memdev. c

# 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;/* open the file Function */INT mem_open (struct inode * inode, struct file * filp) {struct mem_dev * dev; /* obtain the device Number */INT num = minor (inode-> I _rdev); 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; // you can use return 0 for this pointer in the future ;} /* file release function */INT mem_release (struct inode * inode, struct file * filp) {return 0;}/* read function */static ssize_t mem_read (struct file * filp, char _ Use R * Buf, size_t size, loff_t * PPOs) {unsigned long P = * PPOs; unsigned int COUNT = size; 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) // If the read range is exceeded, return 0, indicating that no data is read. Return 0; if (count> memdev_size-p) Count = memdev_size-P;/* read data to the user space */If (copy_to_user (BUF, (void *) (Dev-> Data + p), count) {ret =-efault;} else {* PPOs + = count; ret = count; Printk (kern_info "read % d bytes (s) from % d \ n", Count, P);} return ret ;} /* write function */static ssize_t mem_write (struct file * filp, const char _ User * Buf, size_t size, loff_t * PPOs) {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 the 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 file locating function */static loff_t mem_llseek (struct file * filp, loff_t offset, int whence) {loff_t newpos; Switch (whence) {Case 0: /* seek_set */newpos = offset; break; Case 1:/* seek_cur */newpos = filp-> f_pos + Offset; break; Case 2:/* seek_end */newpos = memdev_size-1 + offset; break; default:/* can't happen */Return-einval ;} if (newpos <0) | (newpos> memdev_size) Return-einval; filp-> f_pos = newpos; 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) {int result; int I; dev_t devno = mkdev (mem_major, 0 ); /* apply for the device ID statically */If (mem_major) Result = register_chrdev_region (devno, 2, "memdev "); else/* dynamically allocate the device Number */{result = alloc_chrdev_region (& devno, 0, 2, "memdev"); mem_major = major (devno);} If (result <0) return result;/* initialize the cdev structure */cdev_init (& cdev, & mem_fops); // associate cdev with mem_fops. owner = this_modu Le; // The owner member indicates who owns the driver and adds "kernel reference module count" to 1; this_module indicates that this module is used by the kernel. This is a macro cdev defined by the kernel. ops = & mem_fops;/* register a character device */cdev_add (& cdev, mkdev (mem_major, 0), memdev_nr_devs ); /* allocate memory for the device description structure */mem_devp = kmalloc (memdev_nr_devs * sizeof (struct mem_dev), gfp_kernel); // we have always used gfp_kernel if (! Mem_devp)/* application failed */{result =-enomem; goto fail_malloc;} memset (mem_devp, 0, sizeof (struct mem_dev )); /* allocate memory for the device */for (I = 0; I <memdev_nr_devs; I ++) {mem_devp [I]. size = memdev_size; mem_devp [I]. data = kmalloc (memdev_size, gfp_kernel); // The allocated address exists in this memset (mem_devp [I]. data, 0, memdev_size);} return 0; fail_malloc: unregister_chrdev_region (devno, 1); 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_license ("GPL"); module_init (memdev_init); module_exit (memdev_exit );

3. Compile source code

1. Copy the two driver source files to the kernel linux-2.6.32.2/Drivers/Char directory

2. Modify the kconfig file in the directory to add

config MEMDEV_DRIVER        tristate "memdev driver"

3. Modify the MAKEFILE file in the directory and add

OBJ-$ (config_hello_driver) + = memdev. o

So far, the file is added to the kernel.

4. Go to the Linux-2.6.32.2 source code root directory to execute

Make menuconfig

In the character device, find the menu item "memdev driver", which is the driver module we just added, and select m

5. Execute in Linux-2.6.32.2 source code root directory

Make modules

You can generate the kernel module File memdev. Ko.

So far, we have compiled the driver module.

4. download and install the driver to the development Edition

1. Download memdev. Ko to the Development Board, move it to the/lib/modules/2.6.29.4-friendlyarm directory, and then execute it in the Development Board.

# Modprobe memdev

(Note that The modprobe command does not require the. Ko suffix, and rmmod is also the case. This will often be forgotten)

Of course, you can also use the insmod command: insmod memdev. Ko

2. Create a device file

# Mknod/dev/memdev0 C 254 0

5. Test

The test code is as follows:

App_mem.c

# 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 ); /* locate the file location again (think about the consequences of not having this command) */fseek (fp0, 0, seek_set);/* clear Buf */strcpy (BUF, "Buf is null! "); Printf (" Buf: % s \ n ", Buf);/* Read Device */fread (BUF, sizeof (BUF), 1, fp0 ); /* Check Result */printf ("Buf: % s \ n", Buf); Return 0 ;}

Compile the program and upload it to the Board for execution.

The program output result is as follows:

  

The results are the same as expected.

 

 

Vi. Summary

I didn't intend to download it to the Development Board to run it. I thought it could run on a virtual machine, but there was always an error in insmod.

Insmod error inserting 'memdev. Ko ':-1 invalid module format

Later, I checked some information on the Internet. This error may be because the kernel code tree is different from the kernel. I checked it with uname-A and found that my kernel version is 2.6.25-14. In addition, I used the file command to view the generated memdev. Ko file and found that it was compiled into a file on the ARM platform. The kernel of my Development Board is the same as the kernel code tree, so I downloaded the experiment on the board and did not see the error just now.

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.