When you start learning to drive, you need Mknod/dev/timer C 500 0 To create a device node manually; The Linux kernel actually provides a set of functions that can be used to automatically create the corresponding device node in the/dev directory when the driver module is loaded. and delete the node at the time of the download .
Device_create (struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *FMT, ... ) paired with Device_destroy (struct class *class,dev_t devt)
Class_create (owner, name) and Class_destroy (struct class *cls);
Code implementation:
/*
*************************************************************************
Environment: Ubuntu 12.04
Cross-compilation tool:arm-none-linux-gnueabi-
Development Board: exynos4412
***********************************************************************************
*/
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>//character device header files
#include <asm/uaccess.h>
#include <linux/timer.h>
#include <linux/device.h>
#define MA 300//main device number
struct class *my_class; Define a class for Udev to automatically create a node
Module_license ("Dual BSD/GPL"); Module License Statement One of three elements
int timer_major=ma; The main device number is used to distinguish different kinds of devices
Timer Device Structure Body
struct Timer_dev {
struct Cdev Cdev; Cdev Structural Body
int counter; How many seconds did you go through?
struct Timer_list s_timer;//device to use timers
}timer_dev;
Timer handler function
static void Timer_handle (unsigned long arg) {
Mod_timer (&timer_dev.s_timer,jiffies+hz);
timer_dev.counter++;
PRINTK (kern_notice "Current jiffies%d\n", jiffies);
}
File Open function
int Timer_open (struct inode *inode,struct file *filp) {
Initialize Timer
Init_timer (&timer_dev.s_timer); Initialize Timer
Timer_dev.s_timer.function=timer_handle; specifying timer handler functions
Timer_dev.s_timer.expires=jiffies+hz; //
Add_timer (&timer_dev.s_timer);//Add Registration Timer
timer_dev.counter=0; Count zeroing
return 0;
}
File Close function
int timer_release (struct inode *inode,struct file *filp) {
Del_timer (&timer_dev.s_timer);
PRINTK ("timer release \ n");
return 0;
}
File Read function
Static ssize_t timer_read (struct file * Filp,char __user *buf,size_t count,loff_t *ppos) {
if (Put_user (timer_dev.counter, (int *) BUF))
Return-efault;
Else
return sizeof (unsigned int);
}
File Operation structure Body
static const struct File_operations Timer_fops = {
. owner = This_module,
. Open = Timer_open,
. Release = Timer_release,
. read = Timer_read,
};
Initialize and register Cdev
static void Timer_setup_cdev (struct Timer_dev *dev,int index) {
int Err,devno =mkdev (timer_major,index); Get the device number
Cdev_init (&dev->cdev,&timer_fops); Character Device Initialization
Err=cdev_add (&dev->cdev,devno,1); Add a character device to the system
if (ERR)//anomaly judgment
{
PRINTK (kern_notice "Error%d adding led%d", err,index);
}
}
Device Driver Module load function
int Timer_init (void) {
int ret;
dev_t devno =mkdev (timer_major,0); Get the device number
/*
*mkdev (major,min);
*major: What type of device does the main device number refer to?
*min: Secondary device number refers to which device is specific
*/
Ret=register_chrdev_region (devno,1, "Timmer");//Registered device number
/*
* Register a character device number (statically assigned)
* Get one or more device numbers for one character drive
*register_chrdev_region (Dev_id,device_num,device_name);
*DEV_ID assigned starting device number (typically 0)
*device_num: Total number of connected device numbers requested (not too large to avoid other major device number conflicts)
*device_name: is the device name that should be connected to this number
*/
if (ret<0)
return ret;
Timer_setup_cdev (&timer_dev,0); Initialize handler function
Automatically create a device node
My_class=class_create (This_module, "timer");
if (Is_err (My_class)) {
PRINTK ("err:failed in creating class.\n");
return-1;
}
Register this device node
Device_create (My_class,null,devno,null, "Timer_dev");
PRINTK ("Timer init, ok\n");
return 0;
}
Device Driver module unload function
void Timer_exit (void) {
dev_t devno =mkdev (timer_major,0); Get the device number
Cdev_del (&timer_dev.cdev);
Device_destroy (MY_CLASS,DEVNO); Unregister This device node
Class_destroy (My_class); //Delete a device node
Unregister_chrdev_region (MKDEV (timer_major,0), 1);//Release device number
PRINTK ("Timer exit ok\n");
}
Module_init (Timer_init); Module loading entry declaration one of three elements
Module_exit (Timer_exit); Module unload entry declaration one of three elements
Execution Result:
[[email protected]] #ls
A.out Dev lib mnt root sys timer.o usr
Bin etc LINUXRC proc Sbin Timer.ko tmp var
Load the Drive module:
[[email protected]] #insmod Timer.ko
[47.760000] Timer init OK
View Driver Module Load Information
[[email protected]] #lsmod
Timer 2172 0-live 0xbf000000 (O)
View the automatically created device nodes
[[email protected]] #ls-l/dev/timer_dev
CRW-RW----1 0 0, 0 Jan 1 00:00/dev/timer_dev
You can see that the automatic creation of the device node succeeded
To unload the drive module:
[[email protected]] #rmmod timer
[243.960000] Timer exit OK
can also be successfully loaded again
[[email protected]] #insmod Timer.ko
[304.940000] Timer init OK
If no pairing is used, the reload will be error-free
Class_destroy (My_class); //Delete a device node
I'm going to block this line and see how the results work.
[[email protected]] #insmod Timer.ko
[445.950000] Timer init OK
[[email protected]] #rmmod Timer.ko
[[email protected]] #insmod Timer.ko
Insmod:can ' t insert ' Timer.ko ': File exists
This error occurs when loading.
Block the next two lines
Device_destroy (MY_CLASS,DEVNO); Unregister This device node
Class_destroy (My_class); //Delete a device node
Results:
[[email protected]] #insmod Timer.ko
[58.595000] Timer init OK
[[email protected]] #ls-l/dev/timer_dev
CRW-RW----1 0 0, 0 Jan 1 00:00/dev/timer_dev
[[email protected]] #rmmod timer
[84.430000] Timer exit OK
The first time there is no problem loading, uninstall when the problem comes, you can see that the display is successful, but look at the following query, is not deleted successfully
[[email protected]] #ls-l/dev/timer_dev
CRW-RW----1 0 0, 0 Jan 1 00:00/dev/timer_dev
The following issue occurs when you load this
[[email protected]] #insmod Timer.ko
[103.780000]------------[Cut here]------------
[103.785000] warning:cpu:0 pid:1203 at fs/sysfs/dir.c:52 sysfs_warn_dup+0x68/0x84 ()
[103.795000] sysfs:cannot create duplicate filename '/class/timer '
[103.800000] Modules linked In:timer (o+) [Last Unloaded:timer]
[103.805000] cpu:0 pid:1203 comm:insmod tainted:g O 3.14.0 #2
[103.810000] [<c0013e10>] (unwind_backtrace) from [<c0011240>] (show_stack+0x10/0x14)
[103.820000] [<c0011240>] (show_stack) from [<c03b874c>] (DUMP_STACK+0X64/0XB4)
[103.825000] [<c03b874c>] (dump_stack) from [<c001ce74>] (warn_slowpath_common+0x68/0x88)
[103.835000] [<c001ce74>] (Warn_slowpath_common) from [<c001cf28>] (warn_slowpath_fmt+0x30/0x40)
[103.845000] [<c001cf28>] (warn_slowpath_fmt) from [<c01092e8>] (sysfs_warn_dup+0x68/0x84)
[103.850000] [<c01092e8>] (sysfs_warn_dup) from [<c0109388>] (sysfs_create_dir_ns+0x84/0x8c)
[103.860000] [<c0109388>] (Sysfs_create_dir_ns) from [<c01d6240>] (KOBJECT_ADD_INTERNAL+0X9C/0X2C0)
[103.870000] [<c01d6240>] (kobject_add_internal) from [<c01d6484>] (kset_register+0x20/0x3c)
[103.880000] [<c01d6484>] (kset_register) from [<c02482b8>] (__class_register+0xac/0x198)
[103.885000] [<c02482b8>] (__class_register) from [<c02483e4>] (__class_create+0x40/0x6c)
[103.895000] [<c02483e4>] (__class_create) from [<bf004168>] (init_module+0x6c/0xec [timer])
[103.900000] [<bf004168>] (init_module [timer]) from [<c00087b4>] (do_one_initcall+0x30/0x144)
[103.910000] [<c00087b4>] (Do_one_initcall) from [<c0074f9c>] (load_module+0x173c/0x1c68)
[103.920000] [<c0074f9c>] (load_module) from [<c00755a4>] (SYS_INIT_MODULE+0XDC/0XE0)
[103.925000] [<c00755a4>] (sys_init_module) from [<c000e420>] (ret_fast_syscall+0x0/0x30)
[103.935000]---[end trace 11ebc48fbb16ce8a]---
[103.940000]------------[Cut here]------------
[103.945000] warning:cpu:0 pid:1203 at lib/kobject.c:240 kobject_add_internal+0x238/0x2c0 ()
[103.950000] kobject_add_internal failed for timer with-eexist, and don ' t try to register things with the same name in the Same directory.
[103.965000] Modules linked In:timer (o+) [Last Unloaded:timer]
[103.970000] cpu:0 pid:1203 comm:insmod tainted:g W O 3.14.0 #2
[103.975000] [<c0013e10>] (unwind_backtrace) from [<c0011240>] (show_stack+0x10/0x14)
[103.985000] [<c0011240>] (show_stack) from [<c03b874c>] (DUMP_STACK+0X64/0XB4)
[103.990000] [<c03b874c>] (dump_stack) from [<c001ce74>] (warn_slowpath_common+0x68/0x88)
[104.000000] [<c001ce74>] (Warn_slowpath_common) from [<c001cf28>] (warn_slowpath_fmt+0x30/0x40)
[104.010000] [<c001cf28>] (warn_slowpath_fmt) from [<c01d63dc>] (KOBJECT_ADD_INTERNAL+0X238/0X2C0)
[104.020000] [<c01d63dc>] (kobject_add_internal) from [<c01d6484>] (kset_register+0x20/0x3c)
[104.025000] [<c01d6484>] (kset_register) from [<c02482b8>] (__class_register+0xac/0x198)
[104.035000] [<c02482b8>] (__class_register) from [<c02483e4>] (__class_create+0x40/0x6c)
[104.040000] [<c02483e4>] (__class_create) from [<bf004168>] (init_module+0x6c/0xec [timer])
[104.050000] [<bf004168>] (init_module [timer]) from [<c00087b4>] (do_one_initcall+0x30/0x144)
[104.060000] [<c00087b4>] (Do_one_initcall) from [<c0074f9c>] (load_module+0x173c/0x1c68)
[104.065000] [<c0074f9c>] (load_module) from [<c00755a4>] (SYS_INIT_MODULE+0XDC/0XE0)
[104.075000] [<c00755a4>] (sys_init_module) from [<c000e420>] (ret_fast_syscall+0x0/0x30)
[104.085000]---[end trace 11ebc48fbb16ce8b]---
[104.085000] err:failed in creating class.
Insmod:can ' t insert ' Timer.ko ': Operation not permitted
[[Email protected]]#
Summary: In the driver writing, many functions are used in pairs, need to pay special attention to the general application is released, there is a new delete
Automatically create device nodes class_create and device_create