Refer to: Linux Device Drivers Chapter 3: scull
Http://oss.org.cn/kernel-book/ldd3/ch03.html
Character devices are the most basic types of Linux device models.
Main. c
# Include "mysc. H "module_license (" GPL "); struct mysc_dev scull_device; struct class * mysc_class; int dn_major, dn_minor; static int mysc_init (void) {dev_t devno = 0; // 1. allocate Dev number dn_minor = 0; assign (& devno, dn_minor, 1, "myscull"); dn_major = major (devno); mysc_class = class_create (this_module, "myscull "); printk ("mysc: devno: % d \ n", dn_major, dn_minor); // 2. init cdev scull_device.ops = & mysc_fops; cdev_init (& scull_device.cdev, & mysc_fops); Modules = this_module; int err = cdev_add (& developers, devno, 1); If (ERR) printk ("error % d \ n", err); // In eldd class_device_create, now device_create -- in my 2.6.35 kernel, the function name is device_create, the device_create (mysc_class, 0, devno, 0, "myscull"); Return 0;} static void mysc_exit (void) {dev_t devno = mkdev (dn_major, dn_minor ); cdev_del (& Strong); unlock (devno, 1); // In eldd class_device_destroy, now device_destroy (mysc_class, devno); class_destroy (mysc_class); printk ("mysc: exiting... \ n ");} module_init (mysc_init); module_exit (mysc_exit );
FoPs. c
#include "mysc.h"struct file_operations mysc_fops={ .owner = THIS_MODULE, // .llseek = mysc_llseek, .read = mysc_read, .write = mysc_write, // .ioctl = mysc_ioctl, .open = mysc_open, .release= mysc_release };#define debug_inode(str) printk(KERN_ALERT "mysc: " str " i_ino = %ld\n", inode->i_ino)ssize_t mysc_read(struct file *fp, char __user *buf, size_t count, loff_t *fpos){ struct mysc_dev *dev = fp->private_data; count=min(count, MYSIZE-*fpos); if (count>0) { copy_to_user(buf, &dev->buf[*fpos], count); *fpos+=count; } return count;}ssize_t mysc_write(struct file *fp, const char __user *buf, size_t count, loff_t *fpos){ struct mysc_dev *dev = fp->private_data; count=min(count, MYSIZE-*fpos); if (count>0) { copy_from_user(&dev->buf[*fpos], buf, count); *fpos+=count; return count; } else return -ENOMEM;}int mysc_open(struct inode *inode, struct file *fp){ struct mysc_dev *dev = container_of(inode->i_cdev, struct mysc_dev, cdev); fp->private_data=dev; //save mysc_dev ptr for other methods. debug_inode("opening device."); return 0;}int mysc_release(struct inode *inode, struct file *fp){ debug_inode("releasing device."); return 0;}
Mysc. h
#ifndef _MYSC_H_#define _MYSC_H_#include <linux/kernel.h>#include <linux/init.h>#include <linux/module.h>#include <linux/errno.h>#include <linux/types.h>#include <linux/cdev.h>#include <linux/device.h>#include <linux/fs.h>#include <asm/uaccess.h>#include <linux/slab.h>#define MYSIZE 1000struct mysc_dev{ char buf[MYSIZE]; struct file_operations *ops; struct cdev cdev;};//fops.cint mysc_open(struct inode *inode, struct file *fp);int mysc_release(struct inode *inode, struct file *fp);ssize_t mysc_read(struct file *fp, char __user *buf, size_t count, loff_t *fpos);ssize_t mysc_write(struct file *fp, const char __user *buf, size_t count, loff_t *fpos);extern struct file_operations mysc_fops;//mysc.cextern int dn_major, dn_minor;extern struct class *mysc_class;#endif
Makefile
KERNELVERSION=$(shell uname -r)KERNELDIR=/lib/modules/$(KERNELVERSION)/buildCC=gccifneq ($(KERNELRELEASE),)mysc-objs := main.o fops.oobj-m := mysc.oelsePWD:=$(shell pwd)modules:$(MAKE) -C $(KERNELDIR) M=$(PWD) modulesmodules_install:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_installclean:rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versionsendif
Usage: After the module is installed, you can read and write content to/dev/myscull with The sudo permission.