EmbLogic's Blog

CHARACTER DRIVER

CHARACTER DRIVER
DEVICE DRIVER: -Device driver is a black box which gives response to a hardware to internal programming interface. Device driver hides the details of working device.

DEVICE DRIVERS ARE OF THREE TYPES:-
1. Character Driver
2. Block Driver
3. Network Driver

Here we will elaborate the working of CHARACTER DRIVER.
in character Driver following are essential function which perform their own specific task:-
Initialization of module
Exit of module
Release function of module from kernel
Creating a SCULL(simple character utility for loadable
locality.
Registering character device in kernel
writing function in character device
Read functionality
Read/write with single threads
Read/write using multiple threaded application using
following synchronization technique:
1. Semaphore and Mutex
2. Completion
3. Spinlock
4. waitque
Proc creat and read
Before staring of functions we should include a common header which contains global headerfile ,global variable and structure which will be describe in functions one by one.
1.INITIALISATION OF MODULE :- Initialisation is main entry point for module in kernel.
module_init is the function which passes address of initialisation function routine as an argument. Printk is output function which prints output. Included headerfiles for init function are #include and #include .
our module named lkm.c can be inserted in kernel after make it by makefile which include path lib/modules/$(shell uname -r)/build .
Our module can be inserted by command insmod lkm.c
lsmod is command uses to check entry of our module in /proc/modules
2.CLEANUP or EXIT FUNCTION OF MODULE:- module can be cleaned up when not in use. This modularity is possible in running state of kernel. rmmod lkm.c is command use to cleanup our moudule. Status of initialisation can be checked using command dmesg which prints message in printk function.

3.REGISTERATION OF SCULL DEVICE:- Before registeration of SCULL device we will create a scull device in header.h which have is type of structure.
Contents of scull device are struct scullqset *scullqset, struct cdev c_dev,quantum_size,data_size,device_size,wcou nt,and qset_size.a global structure scull pointer named *sculldev also declared to take access of scull device.
The registeration of scull device is done using function
alloc_chardev_region which will allocate our device with memory provided by kmalloc function dynamically.
Function kmalloc allocates a continous memory in kernel memory region. In cleanup function module is deallocated using function unregister_chardev_region. And allocatted memory can be free up using function kfree. cdev_del function is used to delete our device from kernel space.
To register our module we needs to add up header file:
#include<linux/module.h
2. #include
3. #include
INITIALISATION OF SCULL DEVICE:
To initialise scull device each element of scull structure should be initialised with finite value. Thease value can be defined as macro in header.h file.in our initialisation we take size as
sculldev->quantum_size=quantum_size;
sculldev->data_size=data_size;
sculldev->qset_size=qset_size;
sculldev->device_size=device_size;
sculldev->scullqset=NULL;
sculldev->wcount=0;
SETUP C_DEV:-
as described in sculldev, cdev is also a another important
parameter of our device which have most important functionality to proceed further:
dev=MKDEV(majorno,lv);
cdev_init(&sculldev[lv].c_dev,&fops);
sculldev[lv].c_dev.owner=THIS_MODULE;
sculldev[lv].c_dev.ops=&fops;
sculldev[lv].c_dev.count=nod;
sculldev[lv].c_dev.dev=dev;
for single device lv=0;
as we can see in first
requrement is to initialise cdev
should be initialised with owner of module
count is no of nod or device
and dev_t dev variable which recognise our module.
And last is address of variable of type structure fileoperation.
OPERATIONS like open,read,write,lseek,release,are mapped
to their corresponding routines with fileoperations structure.
struct file_operations fops=
{
open:scull_open,
release:scull_release,
write:dev_write,
seek:scull_llseek,
read:dev_read
};

OPEN OPERATION:-
To perform any read/write/seek operation on device first we have to open our device using function.
int scull_open(struct inode *, struct file *);
when an user level application will perform a open call routine then open would map to this routine.
Function container_of() will return a address pointing to our device which will be assigned to filep->private_data for further operations.
The mode flags of file permissions can be checked using logical OR( | ) operation of f_flags and O_ACCMODE which is in fileoperations structure defined in #include.

WRITE OPERATION:-
Now its time to write data in device. Before start to write data we should initialise function
struct scullqset
{
void **data;
struct scullqset *next;
};
in structure scullqset double pointer type **data will hold the address of quantums. and single pointer *next will point to the next sullqset. Prototype of write function:-
ssize_t dev_write(struct file *, const char __user *, size_t , loff_t * );
as we see in write functon
1. first parameter is struct file pointer which points to private_data holding the address of our device. And address can be assigned to locally declared variable struct sculldev *lsculldev .
2. Next parameter is __user *buffer which holds data to write in our device come from userspace. Now before writing data in devive further stages are:
allocate memory to struct scullqset
allocate memory to local lscullqset->data qset
allocate memory to lscullqset->data[] quantum
data would be written in quantum using function
copy_from_user defined in #include
3. Third parameter is size of data to write in scullqset.
If size of data is more than 64 byte then create a linklist
and each qset will point to next qset by node *next.
4. The last parameter is offset pointer which allows us position to write in our device. This position is obtained from a flag f_pos in fileoperations structure.
Data writing operation accomplished by writing data in quantum one by one.

READ OPERATION:
Data which have been written in device now can be read from device by user level application using read function.

ssize_t dev_read(struct file *,char __user *,size_t,loff_t *);
as in write function read will also have four parameter to perform task.
1. The pointer of type file will point to the address of device contained in private_data.
2. Second parameter is __user *buffer which holds data read from device by calling function
copy_to_user .
This function will read data from device quantum by quantum and we define size of one quantum is 8 byte.
3.third parameter is size of data to read from device
4. and fourth parameter is offset which directs the pointer to the position to read. If offset is zero then data will be read from starting position.

SYNCHRONIZATION:-
Thare arises some issues when user level applications have more than one thread. And this is possible there may be 100′s of appilications having distinct threads to open,read,write and for close opearation.
In this situation a unpredictable result will be obtained.
There are many malfuctioning of device can happen.
Data can be read before being update(writing).
So we must follow some synchronization technique which helps us to obtain a predecided result.
These synchronisations technique are as:
1. semaphore and mutex
2. spinlock
3. completion
4. waitque

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>