EmbLogic's Blog

An article on character device driver

Device drivers are the one of the basic building block s of operating system. Device driver make the particular piece of hardware to respond to a well-defined internal programming interface. There are three types of device driver

Character Driver
Block Driver
Pipe Driver

In character driver byte by byte transfer of data takes place from user space to kernel space and vice – verse. The only relevant difference between a char device and a regular file is that you can always move back and forth in the regular file, whereas most char devices are just data channels, which you can only access sequentially.

Initialization of Character driver

Initialization of driver module is the first step in any driver programming so in the character driver programming . Each piece of code that can be added to the kernel at run time is called a module. The module is linked dynamically to the running kernel using the insmod command. The rmmod command is used to remove the module entry .

module_init(function_name);
module_exit(function_name);

The module_init() and module_exit() macro defined in <Linux/module.h> are used for initialization of initialization function in kernel using insmod and the removal of the initialization function using rmmod.

Registration and unregistration of Driver

The registration of module is done using different function defined in <Linux/fs.h> . The various functions used for registration of the driver are

register_chrdev(unsigned int major,const char *name, const struct file_operation *fops);
extern int alloc_chrdev_region(dev_t * , unsigned minor_no , unsigned nod, driver name);
extern int register_chrdev_region(dev_t, unsigned, const char *);

(*I have used alloc_chrdev_region for registration)

At the time of removal the unregistration of device is done in clean_up function or exit_function the
function for unregistration of driver are

extern void __unregister_chrdev(unsigned int major, unsigned int baseminor,
unsigned int count, const char *name);
extern void unregister_chrdev_region(dev_t, unsigned);

when registration is done kernel give the minor and major no. called inode no. .Major number are used to represent the driver and minor number represent the number of devices administrate by that particular driver. Kernel identify the driver with their major number . In earlier kernel version total 16 bit are used for major no. and minor no., 8 bit for major no. and 8 bit for minor therefore 255 major no. can be allocated by kernel but in new kernel version 32 bits are used from which 12 bits are used for major no. and rest 20 bits are used for minor no. but we still can use only 255 major no. the reason behind it is the 255 major no are defined in the macro in the header file,dev_t type is used to hold device number both major and minor parts. To obtain the major or minor number of dev_t use :

MAJOR(dev_t dev);
MINOR(dev_t dev);

We use scull as a device memory,just like malloc to get memory in user space Kmalloc is used to get memory in kernel space . The garbage in allocated memory in kernel space is remove by :

memset(void *s ,int c ,size_t n);

The first argument refer to the memory location which is to be replaced by the value in second argument and the third argument indicate how of allocated memory should be cleared.Then the deivce is initalized using :

cdev_init(struct cdev *,struct fileoperations * );

cdev_add(struct cdev *,dev_t , nod);

Open and release:-

The open and release operation is performed by the scull_open and scull_release . Open call prepare the device for the future .We know that every thing is in file format, to set a communication between two file the open function is used it make node for every 32 bit inode number so that particular inode number file can use that node for communication .

Scull_open();
Scull_release();
READ and WRITE operation:-
Once the node is open the read and write operation is performed using scull_write and scull_read.
scull_write is to write on kernel space and scull_read to read data of kernel space for these operation
the call copy_from_user and copy_to_user is used. The mapping of all these function are done through
struct file_operation structure.
scull_write(struct file *,const char __user *,ssize_t,loff_t *);
copy_from_user();
scull_read(struct file *,char __user *,ssize_t,loff_t *);
copy_to_user();
that how the data is read and write from and to kernel memory .

 

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>