/* Driver test code */
# Include <Linux/kernel. h>
# Include <Linux/module. h>
# Include <Linux/init. h>
# Include <Linux/cdev. h>
# Include <Linux/fs. h>
# Include <Linux/sched. h>
# Include <ASM/uaccess. h>
# Include <Linux/device. h>
Module_license ("GPL ");
Static int char_read (struct file * filp, char _ User * buffer, size_t, loff_t *);
Static int char_open (struct inode *, struct file *);
Static int char_write (struct file * filp, const char _ User * buffer, size_t, loff_t *);
Static int char_release (struct inode *, struct file *);
Static int chropen;
Struct cdev * chardev;
Struct class * my_class;
Static int Len;
Static dev_t dev;
Static char *;
Static const struct file_operations char_ops = {
. Read = char_read,
. Write = char_write,
. Open = char_open,
. Release = char_release,
};
Static int _ init char_init (void)
{
Printk (kern_alert "initing... \ n ");
Chardev = cdev_alloc ();
If (chardev = NULL ){
Return-1;
}
If (alloc_chrdev_region (& Dev, 0, 10, "xmimx")/* dynamically allocate device numbers */
{
Printk (kern_alert "register char Dev error \ n ");
Return-1;
}
Chropen = 0;
Len = 0;
Cdev_init (chardev, & char_ops );
If (cdev_add (chardev, Dev, 1 )){
Printk (kern_alert "add char Dev error! \ N ");
}
My_class = class_create (this_module, "xmimx_class");/* create a class */
If (is_err (my_class )){
Printk ("Err: failed in creating class. \ n ");
Return-1;
}
Device_create (my_class, null, Dev, null, "xmimx");/* create a device node and register the device with the system */
Return 0;
}
# Define dp_major major (Dev)
# Define dp_minor minor (Dev)
Static int char_open (struct inode * inode, struct file * file)
{
If (chropen = 0)
Chropen ++;
Else {
Printk (kern_alert "another process open the char device \ n ");
Return-1;
}
Try_module_get (this_module );
Return 0;
}
Static int char_release (struct inode * inode, struct file * file)
{
Chropen --;
Module_put (this_module );
Return 0;
}
Static int char_read (struct file * filp, char _ User * buffer, size_t length, loff_t * offset)
{
Unsigned long nn;
Nn = copy_to_user (buffer, to, length );
Printk ("buffer = % s \ n", buffer );
Return length;
}
Static int char_write (struct file * filp, const char _ User * buffer, size_t length, loff_t * offset)
{
Unsigned long N;
To = (char *) kmalloc (sizeof (char) * (Length + 1), gfp_kernel );
Memset (to, '\ 0', Length + 1 );
N = copy_from_user (to, buffer, length );
Printk ("n = % LD \ n", N );
Printk ("to = % s \ n", );
Return length;
}
Static void _ exit module_close (void)
{
Len = 0;
Printk (kern_alert "unloading... \ n ");
Unregister_chrdev_region (mkdev (dp_major, dp_minor), 10 );
Cdev_del (chardev );
Device_destroy (my_class, Dev );
Class_destroy (my_class );
}
Module_init (char_init );
Module_exit (module_close );
/*************************************** **************************************** */
/* App Code */
# Include <sys/types. h>
# Include <unistd. h>
# Include <fcntl. h>
# Include <Linux/RTC. h>
# Include <Linux/IOCTL. h>
# Include <stdio. h>
# Include <stdlib. h>
Main ()
{
Int FD;
Int I;
Char data [256];
Int retval;
FD = open ("/dev/xmimx", o_rdwr );
If (FD =-1)
{
Perror ("error open \ n ");
Exit (-1 );
}
Printf ("Open/dev/xmimx OK \ n ");
Retval = write (FD, "David Zeng", 10 );
If (retval =-1)
{
Perror ("write error \ n ");
Exit (-1 );
}
Memset (data, '\ 0', 256 );
Retval = read (FD, Data, 10 );
If (retval =-1)
{
Perror ("read error \ n ");
Exit (-1 );
}
Data [retval] = '\ 0 ';
Printf ("read OK: % s \ n", data );
Close (FD );
}
/*************************************** ************/
/***** Makefile *****/
Target = demo2
Kdir =/usr/src/linux-headers-2.6.32-25-generic
Pwd = $ (shell PWD)
OBJ-M: = $ (target). o
Default:
Make-C $ (kdir) M = $ (PWD) Modules
Clean:
Rm-RF *. O *. Ko *. Mod. C. *. CMD *~ . Tmp_versions modules. Order module. symvers $ (target) _ Test
Install:
Sudo insmod $ (target). Ko
Uninstall:
Sudo rmmod $ (target)
Test:
Gcc-o $ (target) _ test. c
/********** For more information, see the other articles ******/