Linux Driver Development Steps (X86 platform)
This article turns from: http://blog.sina.com.cn/s/blog_75f3979401015cwr.html
write the driver and mount the driver to the kernel by mounting it in the following steps:
One: 1> establish a C language program file with a. c suffix (which contains the device name and equipment number, etc.)
2> Set up makefile file (the function is to generate the device file *.ko file by make, which can build its own platform for the necessary equipment files such as: arm and so on. make produces the appropriate device files
Two: In/dev under the establishment of the corresponding device node (device name), with the INSOMD *.ko command to the corresponding driver device files mounted to the kernel.
Three: Write a test file (. c file) to test whether the kernel is nearly successfully mounted to the kernel. (after writing the corresponding test file, use gcc–o filename filename.c (test file name) to produce the corresponding executable file).
Four: If the device-driven mount succeeds, the results will be generated when the test file (./filename) is executed.
Five: The relevant commands may be used:
1.lsmod: List the topics where the kernel has been loaded into the module.
Output:
Module (modular name) size (size) used by (. Use
2.DEMOP: Analyze dependencies of loadable modules, generate MODULES.DEP files and mapping files
3.UNAME–R Displays the kernel version (used when writing makefile)
4.modprobe:linux kernel Add and remove modules (see the Man help document for related parameters)
5.modinfo: Displays information about the kernel module.
6.insmod: Load a module into the Linux kernel, usage: insmod[filename] [module Options ...]
7.rmmod: Delete module in kernel, usage: rmmod [-f,w,s,v][modulename]
8.DMESG: Displays kernel buffers, various kernel information, and the kernel startup information is written to the/var/log/.
Six. Example 1:
First step: Add header files and macro definitions
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/module>
#include <linux/kernel>
Step Two: Add data members related to character device definition and registration
//define device name
#define DEVICE_NAME "test"//device name
#define BUF_SIZE 1024
static char tmpbuf[buf_size];
//define primary and secondary equipment number
static unsigned int testmajor=0;//main
static unsigned int testminor=0;/Times
static struct Cdev *test_cdev;
static dev_t Dev;
Step Three: Increase the Open/release function
static int Test_chardev_open (struct inode *inode,struct file *file)
{
PRINTK ("Open major=%d, minor=%d\n", Imajor (inode),
Iminor (inode));
return 0;
}
static int test_chardev_release (struct inode *inode,struct file *file)
{
PRINTK ("Close major=%d,minor=%d\n", Imajor (inode),
Iminor (inode));
return 0;
}
Step Fourth: Add the Read function
static ssize_t test_chardev_read (struct file *file,char __user *buf,
size_t const count,loff_t *offset)
{
if (Count < buf_size)
{
if (Copy_to_user (buf,tmpbuf,count))
{
printk ("Copy to user fail \ n");
Return-efault;
}
}else{
PRINTK ("read size must be less than%d\n", buf_size);
Return-einval;
}
*offset + = count;
return count;
}
Fifth Step: Add Write function
Static ssize_t test_chardev_write (struct file *file, const char __user*buf,size_t const count,loff_t *offset)
{
if (Count < buf_size)
{
if (Copy_from_user (Tmpbuf,buf,count))
{
PRINTK ("Copy from user fail \ n");
Return-efault;
}
}else{
PRINTK ("Size must be less than%d\n", buf_size);
Return-einval;
}
*offset + = count;
return count;
}
Step Sixth: Add additional File_operations members
static struct File_operations chardev_fops={
. Owner = This_module,
. Read = Test_chardev_read,
. write = Test_chardev_write,
. open = Test_chardev_open,
. Release = Test_chardev_release,
};
Step Seventh: Add equipment number acquisition and equipment registration at the entrance of the module
static int __init chrdev_init (void)
{
int result;
if (testmajor)
{
Dev=mkdev (Testmajor,testminor);//Create device number
result=register_chrdev_region (dev,1,device_name);
} else {
result=alloc_chrdev_region (&dev,testminor,1,device_name);
testmajor=major (dev);
}
if (result<0)
{
PRINTK (kern_warning "led:cannot get major%d \ n", testmajor);
return result ;
}
Test_cdev=cdev_alloc ();
Cdev_init (test_cdev,&chardev_fops);
//test_cdev->ops=&chardev_fops;
test_cdev->owner=this_module;
Result=cdev_add (test_cdev,dev,1);
if (result)
PRINTK ("<1>error%d while register LEDs device!\n", result);
return 0;
}
Step eighth: Increase the device number release and device logoff function in the export function of the module
Unregister_chrdev_region (Mkdev (Testmajor,testminor), 1);
Cdev_del (Test_cdev);
Step nineth: Compile and load the module
Tenth step: According to the device number setup, in the file system to establish the corresponding device node
#mknod/dev/test C XXX XX
Example 2:
Driver files:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/uaccess.h>
#define DEVICENAME "CCCCC"
unsigned int major=221;
unsigned int minor=0;
struct Cdev *abc;
dev_t Dev;
static char bufrh[1024]= "Read success!";
static int Aaaaa_open (struct inode *inodep, struct file *filep)
{
PRINTK ("read success!\n");
return 0;
}
int aaaaa_release (struct inode *inodep, struct file *filep)
{
return 0;
}
Static ssize_t aaaaa_read (struct file *filep, char __user *buf, Size_tcount, loff_t *offset)
{
if (Copy_to_user (buf, BUFRH, 1))
{
PRINTK ("Copy_to_user fail!\n");
}
return 0;
}
ssize_t aaaaa_write (struct file *filep, const char __user *buf,size_t count, loff_t *offse)
{
PRINTK ("write!\n");
return 0;
}
static const struct File_operations FoPs = {
. Owner = This_module,
. open = Aaaaa_open,
. Release = Aaaaa_release,
. Read = Aaaaa_read,
. write = Aaaaa_write,
};
static int __init aaaaa_init (void)
{
int A;
Dev=mkdev (major, minor);
A=register_chrdev_region (Dev, 1, devicename);
Abc=cdev_alloc ();
abc->owner=this_module;
Cdev_init (ABC, &fops);
Cdev_add (ABC, dev, 1);
return 0;
}
static void __exit aaaaa_cleanup (void)
{
Cdev_del (ABC);
Unregister_chrdev_region (Dev, 1);
}
Module_init (Aaaaa_init);
Module_exit (Aaaaa_cleanup);
Module_license ("GPL");
Makefile File:
Obj-m + = FIRSTQD.O (corresponding device file name)
Kerdir =/usr/src/linux-headers-2.6.32-24-generic
#KERDIR =/home/linux2.6/linux #arm骞冲彴
pwd=$ (Shell PWD)
Modules
$ (make)-C $ (Kerdir) m=$ (PWD) modules
Pc:
Gcc-o FRISTQD FIRSTQD.C
Arm:
Arm-linux-gcc-o FRISTQD FIRSTQD.C
Clean
RM-RF *.o *~core *.depend *.cmd *.ko *.mod.c *.tmp_versions
Test file (test.c):
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
Char buf[1024];
Char bufw[1024]= "write success";
int main ()
{
int fd,m,n;
Fd=open ("/dev/aaa", O_RDWR);
if (FD)
{
M=read (fd,buf,100);
printf ("Read kernel:%s\n", buf);
N=write (fd,bufw,10);
}
printf ("Ni Hao");
return 0;
}