1, Makefile
kdir=/home/xxx/s-linux-3.0. * PWD: pwd ) # kernel Modulesobj-M: = globalmem.omodules :Make-C $ (kdir) m= $ (PWD) Modulesclean : rm -rf *.o *.ko *.mod.c *.markesr *.order *. Symvers. Phony:modules Clean
2, GLOBALMEM.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<linux/slab.h>#include<asm/io.h>#include<asm/system.h>#include<asm/uaccess.h>#defineGlobalmem_size 0x1000//4KB//Create device node in the board side.//mknod/dev/globalmem C 0#defineGlobalmem_major 120//Preset Major number//Define IOCTL cmd#defineGlobalmem_magic 0x01#defineMem_clear _io (globalmem_magic, 0)Static intGlobalmem_major =Globalmem_major;//globalmem structstructGlobalmem_dev {structCdev Cdev;//Cdev structUnsignedCharMem[globalmem_size];//Global Memory};structGlobalmem_dev *GLOBALMEM_DEVP;//device struct InstanceintGlobalmem_open (structInode *inode,structFile *Filp) { //set device struct pointer to file Privatedata pointerFilp->private_data =GLOBALMEM_DEVP; return 0;}intGlobalmem_release (structInode *inode,structFile *Filp) { return 0;}Staticssize_t Globalmem_read (structFile *filp,Char__user *buf, size_t size, loff_t*PPOs) {unsignedLongp = *PPOs; unsignedintCount =size; intRET =0; structGlobalmem_dev *dev = filp->private_data;//get device struct pointer//Analysis and get valid read length if(P >= globalmem_size)//Overflow return 0; if(Count > Globalmem_size-p)//count is too largeCount = globalmem_size-p; //kernel buf-user buf if(Copy_to_user (BUF, (void*) (Dev->mem +p), (count)) RET= -Efault; Else { *ppos + =count; RET=count; PRINTK (Kern_info"read%d bytes from%ld\n", Count, p); } returnret;}Staticssize_t Globalmem_write (structFile *filp,Const Char__user *buf, size_t size, loff_t*PPOs) {unsignedLongp = *PPOs; unsignedintCount =size; intRET =0; structGlobalmem_dev *dev = filp->private_data;//get device stuct pointer//Analysis and get valid write length if(P >= globalmem_size)//Write Overflow return 0; if(Count > Globalmem_size-p)//write count is too largeCount = globalmem_size-p; //user buf-Kernel buf if(Copy_from_user (Dev->mem +p, buf, Count)) RET= -Efault; Else { *ppos + =count; RET=count; PRINTK (Kern_info"written%d bytes from%ld\n", Count, p); } returnret;}Staticloff_t Globalmem_llseek (structFile *filp, loff_t offset,intorig) {loff_t ret=0; Switch(orig) { Case 0://From the file head if(Offset <0|| ((unsignedint) Offset >globalmem_size)) {ret= -EINVAL; Break; } FILP->f_pos = (unsignedint) offset; RET= filp->F_pos; Break; Case 1://From current position if((Filp->f_pos + offset) > Globalmem_size | | (Filp->f_pos + offset) <0) {ret= -EINVAL; Break; } FILP->f_pos + =offset; RET= filp->F_pos; Break; } returnret;}Static LongGlobalmem_ioctl (structFile *filp, unsignedintCMD, unsignedLongArg) { structGlobalmem_dev *dev = filp->private_data;//get device stuct pointer Switch(cmd) { CaseMem_clear:memset (Dev->mem,0, globalmem_size); PRINTK (Kern_info"Globalmem is set to zero\n"); Break; default: return-einval;//Not supported } return 0;}//file Operations structStatic Const structFile_operations Globalmem_fops ={. Owner=this_module,. Llseek=Globalmem_llseek,. Read=Globalmem_read,. Write=globalmem_write,. Unlocked_ioctl=globalmem_ioctl,. Open=Globalmem_open,. Release=Globalmem_release,};//init and add cdev structStatic voidGlobalmem_setup_cdev (structGlobalmem_dev * Dev,intindex) { interr; intDevno = MKDEV (Globalmem_major,0); Cdev_init (&dev->cdev, &globalmem_fops); Err= Cdev_add (&dev->cdev, Devno,1); if(Err) printk (Kern_notice"Error%d adding Globalmem", err);}//globalmem device init functionintGlobalmem_init (void){ intresult; dev_t Devno= MKDEV (Globalmem_major,0); //Apply Globalmem Device kernel region if(globalmem_major) result= Register_chrdev_region (Devno,1,"Globalmem"); Else { //get major No dynamicallyresult = Alloc_chrdev_region (&devno,0,1,"Globalmem"); Globalmem_major=MAJOR (DEVNO); } if(Result <0) returnresult; //apply device struct memoryGLOBALMEM_DEVP = Kmalloc (sizeof(structGlobalmem_dev), Gfp_kernel); if(!GLOBALMEM_DEVP) {Result= -Enomem; GotoFail_malloc; } memset (GLOBALMEM_DEVP,0,sizeof(structGlobalmem_dev)); Globalmem_setup_cdev (GLOBALMEM_DEVP,0); return 0; Fail_malloc:unregister_chrdev_region (Devno,1); returnresult;}//Globalmem device Exit FunctionvoidGlobalmem_exit (void){ //del cdev structCdev_del (&globalmem_devp->Cdev); //Free device struct memoryKfree (GLOBALMEM_DEVP); //Unregister device regionUnregister_chrdev_region (MKDEV (Globalmem_major,0),1); }module_param (Globalmem_major,int, S_irugo); Module_init (Globalmem_init); Module_exit (Globalmem_exit); Module_author ("TT <[email protected]>"); Module_license ("Dual BSD/GPL");
Globalmem character device driver implementation under Linux 3.0.35