After learning the character driver, is according to the Song Baohua Linux device Driver Development explanation study, the code practice knocks over again, oneself also understood.
The main character driver is some open,close,read,write and other operations
Call the underlying function that you wrote through the upper layer
Write code here#include <linux/fs.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/cdev.h>#include <linux/mm.h>#include <linux/sched.h>#include <linux/init.h>#include <asm/io.h>#include <asm/system.h>#include <asm/uaccess.h>#define GLOBALMEM_SIZE 0x1000/* Global memory 4kb*/#define MEM_CLEAR 0x1/* Clear global memory * /#define GLOBALMEM_MAJOR 250/* main device number * /Static intGlobalmem_major = Globalmem_major;structglobalmem_dev{structCdev Cdev;unsigned CharMem[globalmem_size];};structGlobalmem_dev *GLOBALMEM_DEVP;/ * Global structure body * /intGlobalmem_open (structinode* Inode,structfile* filp) {filp->private_data = GLOBALMEM_DEVP;//Assign the device structure pointer value to the file private data pointer return 0;}intGlobalmem_release (structinode* Inode,structfile* Filp) {structglobalmem_dev* dev = filp->private_data;return 0;}Static intGlobalmem_ioctl (structInode* INODEP,structFile* Filp,unsigned intCmdunsigned LongARG) {structglobalmem_dev* dev = filp->private_data;return 0;}Staticssize_t Globalmem_read (structFile* Filp,Char__user *buf, size_t count, loff_t *ppos) {structglobalmem_dev* dev = filp->private_data;unsigned Longp = *ppos;intRET =0;if(P >= globalmem_size)//offset exceeds array range return 0;if(Count > Globalmem_size-p)//The number of reads is too largeCount = globalmem_size-p;//read from the kernel to the user if(Copy_to_user (Buf,dev->mem + p,count)) ret =-Efault;//efault parameter buf point to invalid memory address Else{*ppos + = count; ret = count; PRINTK (Kern_info"read%d bytes from%x\n", count,p); }returnRET;}Staticssize_t Globalmem_write (structFile* Filp,Char__user *buf, size_t count, loff_t *ppos) {structglobalmem_dev* dev = filp->private_data;unsigned Longp = *ppos;intRET =0;if(P >= globalmem_size)//offset exceeds kernel space size return 0;if(Count > Globalmem_size-p)//The number of writes exceeds the existingCount = globalmem_size-p;//write from user to kernel if(Copy_from_user (Dev->mem + p, (void*) buf,count)) ret =-Efault;Else{*ppos + = count; ret = count; PRINTK (Kern_info"Write%d bytes from%x\n", Count,dev->mem + P); }returnRET;}//filp is the kernel file structure bodyStaticloff_t Globalmem_llseek (structfile* Filp, loff_t offset,intOrig) {structglobalmem_dev* dev = filp->private_data;intRet//seek_set 0 File start //seek_cur 1 Current position //seek_end 2 File footer Switch(orig) { Case 0:if(Offset <0) {ret =-EINVAL; Break; }if(Offset > Globalmem_size) {ret =-EINVAL; Break; } Filp->f_pos = (unsigned int) offset; RET = filp->f_pos; Break; Case 1:if(Offset > Globalmem_size) {ret =-EINVAL; Break; }if(Filp->f_pos + offset > Globalmem_size) {ret =-EINVAL; Break; } Filp->f_pos + = offset; RET = filp->f_pos; Break; Case 2:if(Offset >0) {ret =-EINVAL;//At end of file, only offset assignment Break; }if(Offset + Globalmem_size <0) {ret =-EINVAL; Break; } Filp->f_pos + = offset; RET = filp->f_pos; Break;default: ; }return 0;}Static Const structFile_operations globalmem_fops = {. Owner = This_module,. Open = Globalmem_open,. Read = Globalmem_read,. Writ E = globalmem_write,. Release = Globalmem_release,. Llseek = Globalmem_llseek,. Compat_ioctl = Globalmem_ioctl};Static voidGlobalmem_setup_dev (structglobalmem_dev* Globalmem_dev,intIndex) {intErr,devno; Devno = MKDEV (Globalmem_major,0); Cdev_init (&globalmem_dev->cdev,&globalmem_fops); Err = Cdev_add (&globalmem_dev->cdev,devno,1);if(ERR) {PRINTK (Kern_notice"ERROR%d adding Globalmem%d", Err,index); }}Static int__init Globalmem_init (void) {PRINTK (kern_info"Globalmem_init");intResult dev_t Devno = MKDEV (Globalmem_major,0);//According to the main device number, or the device number, the general device number is 0 if(Globalmem_major! =0) Register_chrdev_region (Devno,1,"Globalmem_dev");Else{result = Alloc_chrdev_region (&devno,0,1,"Globalmem_dev");//Automatically assign a device numberGlobalmem_major = Major (Devno); }if(Result <0)returnResult//Dynamic application structure body storageGLOBALMEM_DEVP = Kmalloc (sizeof(structGlobalmem_dev), Gfp_kernel);if(!GLOBALMEM_DEVP)GotoFail_malloc;memset(GLOBALMEM_DEVP,0,sizeof(structGlobalmem_dev)); Globalmem_setup_dev (GLOBALMEM_DEVP,0);return 0; Fail_malloc:unregister_chrdev_region (Devno,1);returnResult;}Static int__exit Globalmem_exit (void) {PRINTK (kern_info"Globalmem_exit ..."); dev_t Devno; Devno = MKDEV (Globalmem_major,0); Cdev_del (&globalmem_devp->cdev);//Delete Cdev structureUnregister_chrdev_region (Devno,1);//Logout deviceKfree (GLOBALMEM_DEVP);return 0;} Module_init (Globalmem_init); Module_exit (Globalmem_exit);
Makefile
KVERS = $(shell uname -r)obj-m += globalmem_private.obuild:kernel_moduleskernel_modules: make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modulesinsmod: insmod globalmem.koclean: make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modules clean
Test program
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define PATH"/dev/globalmem_ Dev " int Main () {char buf[] = "Hello word!\n" ; int fd = open (PATH,O_RDWR); if (FD = =-1 ) {perror ( "open" ); exit (1 ); } write (Fd,buf,sizeof (BUF)); Close (FD);}
Execution results
Linux character driver