Character Device Driver template for Linux driver Learning

Source: Internet
Author: User

Today I sorted out the character device driver template, separated by three files.

The initialization of the Main. c driver.

Loadmod. C provides functions for installing and detaching drivers.

Fileops. c file operation function.

Makefile

#KERNELDIR = /home/fontlose/board/tx2416/kernelsom2416KERNELDIR = /usr/src/kernels/2.6.35.13-92.fc14.i686/PWD := $(shell pwd)#CC    = arm-linux-gccmoddev-objs=main.o fileops.o loadmod.oobj-m+=moddev.o modules:$(MAKE) -C $(KERNELDIR) M=$(PWD) modulesclean:rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions.PHONY: modules clean 

Main. c

#include <linux/module.h>#include <linux/kernel.h>#include <linux/device.h>#include <linux/init.h>#include "loadmod.h"#include "fileops.h"MODULE_AUTHOR("my name");MODULE_LICENSE("Dual BSD/GPL");#define MAJORNUM  0#define MINJORNUM 60 struct file_operations ops={   .owner=THIS_MODULE,   .open=fileops_open,   .write=fileops_write,   .read=fileops_read,   .release=fileops_release};static int template_init(void){ if ( install_chardev(MAJORNUM,MINJORNUM,4,"moduledev","modclass",&ops))         return -1;  if(fileops_init())  {    uninstall_chardev();      return -1;  }  return 0;}static void template_exit(void){  uninstall_chardev();  fileops_destroy();  printk(KERN_ALERT "goodbye\n");}module_init(template_init);module_exit(template_exit);

Loadmod. h

#ifndef   __LOADMOD_H__#define  __LOADMOD_H__#include <linux/fs.h>  extern unsigned char install_chardev(int major_i,int minor_i,unsigned char count,char*devname,char*classname,struct file_operations *ops);  extern int uninstall_chardev(void);#endif

Loadmod. c

# Include <Linux/module. h> # include <Linux/errno. h> # include <Linux/kernel. h> # include <Linux/device. h >#include <Linux/kdev_t.h> # include <Linux/err. h> # include <Linux/cdev. h> # include <Linux/init. h> # include <Linux/Fs. h> # include <Linux/string. h> static struct cdev cdev_install; // static struct class * class_install; // static int major_install, minor_install; // static unsigned char count_install; // *** INS Tall_chardev character device registration function * @ major_ I master device Number * @ minor_ I sub-device Number * @ count number of devices * @ devname device name + registered device name automatically generates devname + times under/dev file of the device Number * @ classname device class name * @ ops file operation data structure */unsigned char install_chardev (INT major_ I, int minor_ I, unsigned char count, char * devname, char * classname, struct file_operations * OPS) {// Step 1: register the device number int I; dev_t dev; if (major_ I = 0) // dynamically apply for a master device number {int res = alloc_chrdev_region (& Dev, minor_ I, Count, devnam E); If (RES) {printk (kern_alert "alloc chrdev region fail! \ N "); Return-1;} major_ I = major (Dev);} else {int res; Dev = mkdev (major_ I, minor_ I); Res = register_chrdev_region (Dev, count, devname); If (RES) {printk (kern_alert "register chrdev region fail! \ N "); Return-1 ;}} major_install = major_ I; minor_install = minor_ I; count_install = count; // Step 2: register the device cdev_install.count = 0; If (Ops! = 0) {cdev_init (& cdev_install, OPS); cdev_install.owner = this_module; cdev_install.ops = OPS; If (cdev_add (& cdev_install, Dev, count_install) {Dev, count_install ); printk (kern_alert "cdev add Fail! \ N "); Return-1 ;}// Step 3: create a device node. Note that class_device_create and class_device_destroy are used in Linux 2.6 // earlier versions, later versions use device_create and device_destroy class_install = class_create (this_module, classname); If (is_err (class_install) {If (cdev_install.count> 0) cdev_del (& cdev_install); Dev, count_install); printk (kern_alert "class creat fail! \ N "); Return-1 ;}for (I = 0; I <count; I ++) {device_create (class_install, null, mkdev (major_install, minor_install + I ), null, "% S % d", devname, minor_install + I);} printk (kern_alert "device initial success Major: % d Minor: % d! \ N ", major_install, minor_install); Return 0;}/*** uninstall_chardev uninstall character device */INT uninstall_chardev (void) {int I; If (cdev_install.count> 0) cdev_del (& cdev_install); unregister_chrdev_region (mkdev (major_install, minor_install), count_install); for (I = 0; I <count_install; I ++) {device_destroy (class_install, mkdev (major_install, minor_install + I);} class_destroy (class_install); Return 0 ;}

Fileops. h

#ifndef __FILEOPS_H__#define __FILEOPS_H__#include <linux/fs.h>extern int  fileops_init(void);extern void fileops_destroy(void);extern int fileops_open(struct inode *inode, struct file *filp);extern int fileops_release(struct inode *inode,struct file *filp);extern ssize_t fileops_read(struct file *filp, char __user *buff, size_t count, loff_t *offp);extern ssize_t fileops_write(struct file *filp, const char __user *buff, size_t count, loff_t *offp);extern int fileops_ioctl(struct inode *, struct file *, unsigned int, unsigned long);#endif


Fileops. c

# Include <Linux/init. h> # include <Linux/kernel. h >#include <Linux/kdev_t.h> # include <Linux/err. h> # include <Linux/cdev. h> # include <Linux/Fs. h> # include "fileops. H "# include <ASM/uaccess. h>/*** called during initialization */INT fileops_init (void) {return 0 ;} /*** the release function calls the */void fileops_destroy (void) {}/ *** file opening driver during module uninstallation to prepare for subsequent operations, if you do not enable the default function, * initialize the device. If necessary, initialize the index node of the filp-> private_data ** @ inode file to store the basic information of the file and directory, determine the specific device * @ filp */INT fileops_open (struct inode * inode, struct file * filp) based on the number of times in the inode structure) {printk (kern_alert "fileops_open \ n"); Return 0 ;}/ *** disable the memory used to release the open application to close the device */INT fileops_release (struct inode * inode, struct file * filp) {printk (kern_alert "fileops_release \ n"); Return 0 ;} /*** read the device * @ filp. Generally, private_data data is operated. * @ Buff: the cache of the user space, used to store the read data * @ count the size of the data the user wants to read * @ OFFP the location of the file the user is accessing * the actual read size negative number is returned, indicating an error */ssize_t fileops_read (struct file * filp, char _ User * buff, size_t count, loff_t * OFFP) {/* update OFFP */printk (kern_alert "fileops_read \ n"); Return 0 ;} /*** write the device * @ filp to perform private_data operations * @ buff user space cache, used to store the data to be written * @ count the data size the user wants to write * @ OFFP the file location the user is accessing * return the actual write size negative number indicating an error */ssize_t fileops_write (struct file * filp, const char _ User * buff, size_t count, loff_t * OFFP) {/* The system call will always write until the write count is sufficient. If the return value is less than count, this method will be called again until an error is returned or count */printk (kern_alert "fileops_write \ n"); Return count;} is written ;} /*** fileops_ioctl IOCTL System Call provides a method for issuing device-specific commands * @ inode * @ filp * @ cmd * @ Arg */INT fileops_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, unsigned long Arg) {printk (kern_alert "fileops_ioctl \ n"); Return 0 ;}

Test Results

[root@localhost module]# makemake -C /usr/src/kernels/2.6.35.13-92.fc14.i686/ M=/home/fontlose/board/tx2416/rootfs/usr/ldds/module modulesmake[1]: Entering directory `/usr/src/kernels/2.6.35.13-92.fc14.i686'  CC [M]  /home/fontlose/board/tx2416/rootfs/usr/ldds/module/main.o  CC [M]  /home/fontlose/board/tx2416/rootfs/usr/ldds/module/fileops.o  CC [M]  /home/fontlose/board/tx2416/rootfs/usr/ldds/module/loadmod.o  LD [M]  /home/fontlose/board/tx2416/rootfs/usr/ldds/module/moddev.o  Building modules, stage 2.  MODPOST 1 modules  CC      /home/fontlose/board/tx2416/rootfs/usr/ldds/module/moddev.mod.o  LD [M]  /home/fontlose/board/tx2416/rootfs/usr/ldds/module/moddev.komake[1]: Leaving directory `/usr/src/kernels/2.6.35.13-92.fc14.i686'[root@localhost module]# dmesg|tail -2[31864.045477] device initial success major:247 minor:60![31872.877461] goodbye[root@localhost module]# ls /dev/moduledev6*/dev/moduledev60  /dev/moduledev61  /dev/moduledev62  /dev/moduledev63[root@localhost module]# ls /sys/class/modclass/moduledev60  moduledev61  moduledev62  moduledev63[root@localhost module]# echo 1234 > /dev/moduledev60 [root@localhost module]# dmesg|tail -3[32022.480159] fileops_open[32022.480171] fileops_write[32022.480174] fileops_release

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.