Simulating a virtual register device driver
1. Write the driver
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
int dev1_registers[5];
int dev2_registers[5];
struct Cdev Cdev;
dev_t Devno;
/* File Open function */
int Mem_open (struct inode *inode, struct file *filp)
{
/* Get the secondary device number */
int num = MINOR (Inode->i_rdev);
if (num==0)
Filp->private_data = dev1_registers;
else if (num = = 1)
Filp->private_data = dev2_registers;
Else
Return-enodev; Invalid secondary device number
return 0;
}
/* File deallocation function */
int mem_release (struct inode *inode, struct file *filp)
{
return 0;
}
/* Read function */
Static ssize_t mem_read (struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
unsigned long p = *ppos;
unsigned int count = size;
int ret = 0;
int *register_addr = filp->private_data; /* Get the device's register base address */
/* Determine if the read position is valid */
if (P >= 5*sizeof (int))
return 0;
if (Count > 5*sizeof (int)-P)
Count = 5*sizeof (int)-p;
/* Read data to User space */
if (Copy_to_user (buf, Register_addr+p, Count))
{
ret =-efault;
}
Else
{
*ppos + = count;
ret = count;
}
return ret;
}
/* Write function */
Static ssize_t mem_write (struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
unsigned long p = *ppos;
unsigned int count = size;
int ret = 0;
int *register_addr = filp->private_data; /* Get the device's register address */
/* Parse and get a valid write length */
if (P >= 5*sizeof (int))
return 0;
if (Count > 5*sizeof (int)-P)
Count = 5*sizeof (int)-p;
/* Write data from user space */
if (Copy_from_user (Register_addr + p, buf, Count))
ret =-efault;
Else
{
*ppos + = count;
ret = count;
}
return ret;
}
/* Seek file Locator function */
Static loff_t mem_llseek (struct file *filp, loff_t offset, int whence)
{
loff_t Newpos;
Switch (whence) {
Case Seek_set:
Newpos = offset;
Break
Case Seek_cur:
Newpos = Filp->f_pos + offset;
Break
Case Seek_end:
Newpos = 5*sizeof (int)-1 + offset;
Break
Default
Return-einval;
}
if ((newpos<0) | | | (newpos>5*sizeof (int)))
Return-einval;
Filp->f_pos = Newpos;
return newpos;
}
/* File operation structure */
static const struct File_operations Mem_fops =
{
. Llseek = Mem_llseek,
. Read = Mem_read,
. write = Mem_write,
. open = Mem_open,
. Release = Mem_release,
};
/* Device driver module load function */
static int memdev_init (void)
{
/* Initialize the CDEV structure */
Cdev_init (&cdev, &mem_fops);
/* Register character device */
Alloc_chrdev_region (&devno, 0, 2, "Memdev");
Cdev_add (&cdev, Devno, 2);
}
/* Module Unload function */
static void Memdev_exit (void)
{
Cdev_del (&cdev); /* Unregister the device */
Unregister_chrdev_region (Devno, 2); /* Release the device number */
}
Module_license ("GPL");
Module_init (Memdev_init);
Module_exit (Memdev_exit);
2. Create a device file, first view the device number in the file system on the Development Board
Cat/proc/devices find the device number for Memdev, here I am 252
Mknod dev/memdev0 C 252 0
3. Writing the write.c file
Vim write.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main ()
{
int FD =0;//
int src = 2013;
Fd=open ("/dev/memdev0", O_RDWR);//Open the file in a readable and writable way, open it
will return an FD,
Write (fd,&src,sizeof (int)); writes data to the file, writes FD First, and then writes
Data, the size of the data.
Close (FD);
}
4. Write read data read.c file
Vim READ_MEM.C
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main ()
{
int fd = 0;
int dst=0;
FD = open ("/dev/memdev0", O_RDWR);
Read (fd,&dst,sizeof (int));
printf ("DST is%d\n", DST);
return 0;
}
5. Writing Makefile
Omitted here, very simple.
Make
Arm-linux-gcc-static Write.c-o Write
Arm-linux-gcc-static Read.c-o Read
6. Copy the compiled modules and write read copies to the NFS file system
Installing the kernel module Insmod Memdev.ko
./write
./read
Character Device driver Example