All about programming in GNU/LINUX

Linux Kernel

A simple Linux Driver : Allocating the Major Minor number

The first step in writing any Linux Device driver is to allocate a Major , Minor pair for the driver , this is a simple Linux Device Driver which allocates the Major , Minor pair and prints the same into DMESG


#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>

static dev_t first;

static int __init my_init(void) /*constructor*/
{
    int ret;

    printk(KERN_INFO "Drivre is being registered");
    if((ret = alloc_chrdev_region(&first,0,3,"Rao")) < 0) /*dynamic allocatin of Major , minor numbers*/
    {

        return ret;
    }
    printk(KERN_INFO "<MAJOR , MINOR ><%d %d>\n" , MAJOR(first),MINOR(first)); /*printing the Major , Minor pair into the dmesg*/
    return 0;
}

static void __exit my_exit(void) /*destructor function , executed when the driver is removed*/
{
    unregister_chrdev_region(first,3); 
    printk(KERN_INFO "dRIVER REMOVED");
}

    module_init(my_init);
    modue_exit(my_exit);
    
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("KARTHIC RAO");
    MODULE_DESCRIPTION("A SIMPLE DRIVER OF MINE");

here is the MAKEFILE for the driver

# If called directly from the command line, invoke the kernel build system.
ifeq ($(KERNELRELEASE),)

	KERNEL_SOURCE := /usr/src/linux-headers-$(shell uname -r)
	PWD := $(shell pwd)
default:
	$(MAKE) -C $(KERNEL_SOURCE) SUBDIRS=$(PWD) modules

clean:
	$(MAKE) -C $(KERNEL_SOURCE) SUBDIRS=$(PWD) clean

# Otherwise KERNELRELEASE is defined; we've been invoked from the
# kernel build system and can use its language.
else

	obj-m := simple_driver.o

endif

Linux-Device-Driver-5:Dynamic Major number allocation for the Driver

 
The Linux kernel Identifies a driver by its <major,monor> number pair .Here is the listing of /dev  Image

The fifth column corresponds to the major number of the devices and the 6th row correponds to the minor number of the device.

The same major number and can assigned to another driver but it will have a different minor number .
There is always a possibility that the major number assigned to a driver already exist and is being by another driver.
To prevent this its always better to dynamically assign the Major nubmer to a  driver and let the kernel allocate a Major number which is freely available at the time of driver registration .
This is achieved by using the following call

int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);

1.The first parameter is the pointer to a variable of data type dev_t , the call fills the variable with the value of the new dynamically assigned major number .
2.The second parameter the starting Minor number to be paired up along with the major number and the 3rd parameter is the total number of minor number required to be assingned starting from the minor nubmer specified in the second argument (second parameter) to the call .
3.Any Device Driver in Linux which is assigned a Major number by the kernel will be listed by the kernel in the file /proc/devices  with name of the device and its Major Number .The fourth argument is the name with which the device will be listed in the file /proc/devices .
Image
unregister_chrdev_region(Dev_t Dev,unsigned int count); is used to unregister the registered device .


Linux Device Drivers-4 : The V.F.S Connection

 To make use of a character device driver , the associated character device file (usually located under /dev) is to be used .Using the following command gives you the list of all character device files in /dev

 ls -l /dev | grep “^c”

Image

 For any user-level application to access the underlying hardware , it should make use of the device driver corresponding to the device . But communication with the device driver can only be made by performing file operations on the device file corresponding to the device (usually located under /dev).

Therefore for any user-level application to get services out of a hardware , it should perform file operations on the corresponding device files .

 The character device driver and the its corresponding device file are connected togetby V.F.S(Virtual File system) . The functions implemented inside the driver will perform her the low-level file access into the underlying hardware .

 From Linux kernel 2.6 onwards there can exist multiple drivers under same MAJOR.NO

 The connection of the device file with the driver is done by means of its <MAJOR.NO,MINOR.NO> pair .This connection is established by using the following to API’s in the driver .These calls registers a <MAJOR,MINOR> pair for the driver. Later any device file created by assigning the same major , minor number will be linked to the corresponding driver .

 int register_chrdev_region(dev_t first,unsigned int no_of_minors,char *name);

 This call associates the driver with the <Major,MINOR> pair stored in the variable first.The variable no_of_minors specifies the no.of.minor numbers to be registered .

 Sometimes the Major number requested may be already allocated and may not be free.So its better to dynamically allocate the MAJOR number and let kernel search a free MAJOR number and assign the same .The following function is used to achieve the purpose .

 int alloc_chrdev_region(dev_t *first,unsigned int first_minor,unsigned int no_of_minors,char *name);

 When any file operations are performed on a device file , it is passed onto the driver my V.F.S .

To achieve this purpose the corresponding functions to be invoked by the driver(functions written inside the driver code) when different file operations* performed on the device file have to be registered with the V.F.S.

This registration is first done by initializing the structure file_operations and then handing the structure

to V.F.S by using the function cdev_add which is declared under <linux/cdev.h>

refer:http://www.linuxforu.com/2011/04/character-device-files-creation-operations/


Linux device Drivers -3:The layers

The Driver is just the part of the flow or the linkage from an application to the low-level access .
This linkage involves four parts
1)The Application
2)The Device file (usually created under /dev)
4)The Device Driver
4)The Hardware device and Low/level Device access

Image

A Device may not always have a physical existance ex:/dev/null , a Device could just have a logical existance.For such a logical device the fourth part of the flow ,i.e the Hardware Device and Low/level Device access doesnt exist.

An explicit connection has to be established between adjacent layers(the 4 parts) of the flow to have an complete Application which could access the underlying hardware and get the job done.That is an explicit connection has to estalished b/w
A)The Application and the Device Device
  -This is achieved by reading or writing into the device file under /dev.The application program could execute system calls to connect these two layers .

B)The Device file and The Device Driver
 -This is achieved by registrations done by the device driver for the Major and Minor number s of the device .The device driver uses kernel space API’s to achieve this.

C)The Device Driver and The Hardware Device
 -The Driver uses low-level kernel space API’s to achieve this .

For a Device like /dev/null which just has a logical existance the part C(The link b/w the Driver and the hardware device) of the connection doesnt exist.


Short note on Linux Kernel-2

  1. Processes need resources .

  2. When multiple processes are running concurrently , These resources are to be shared between them , resources like CPU time , Disk space , memory and network .

  3. Kernel handles these tasks and acts as a resource manager

  4. Applications just have connection with the kernel , which in turn interacts with the hardware are services to the applications

  5. Kernel acts as abstract layer for the applications , i,e applications need not take care of inner implementations , application just need to bother about giving a call to kernel which takes care of everything .

  6. Linux is a multitasking system where it appears that multiple processes are executing concurrently.Each of these processes are given an illusion that CPU is available to them all the time.But in reality kernel switches b/w the processes at short internals to give these processes the illusion of simultaneous processing.The process is called as task switching and the Scheduler of the Kernel is in charge of this duty.

 


Linux Device Drivers-1:Introduction to Device Drivers in Linux

The programs written for the LINUX kernel , that is the kernel programs cannot use headers and function from any library .they cannot make use C headers and their library functions.

Then the obvious question would be that which are  the HEADERS and FUNCTIONS does DEVICE DRIVER and KERNEL PROGRAMS in LINUX make use of??

Kernel programs and device drivers make use of headers which they obtain from the kernel source tree

issuing the command would get you into the path where these kernel headers reside

“cd /lib/modules/$(uname -r)/build/include/linux”
The kernel and device driver programs make use of these headers and functions within them .No External Libraries can be linked , not even C library or its headers found in /usr/include can be used to write device drivers or kernel programs.

After kernel programs or device drivers are written they are compiled and linked to the executable version of these files called as Kernel Modules with .ko extension.A Makefile is created for  these files which are to be compiled and linked.The ‘make’ program is made use of to achieve this purpose.

Later these kernel modules are loaded on top of the kernel dynamically using ‘insmod’ command .lsmod command gives you the list of all kernel modules on top of the kernel.Linux kernel is dynamic , addition and removal of kernel modules can done without the need for restarting the system .The running module can be removed by using ‘rmmod’ command.

By default all the kernel messages from printk function goes to /var/log/syslog file.This can viewed by using ‘dmesg’ command.
/proc/devices contain the list of all configured devices

 

 


Process Priorities by the linux scheduler

In multitasking systems inspite of there will many processes in memory at a given point of time ,but only one at a time will be in runnable state . The scheduler decides the the processes sequence to be run .

 

There are two types of multitasking systems

1)co-operative

2)preemptive

 

In preemptive multitasking, the scheduler decides

when a process is to cease running and a new process is to begin running , the act of involuntarily suspending a running process is called preemption.

 

One of the common scheduling policy is priority based scheduling.More time-slice is provided for processes with higher priority .The priority of a process is indicated by its nice value.Nice value ranges from -20 to +19 .Priority is inversely proportional to its nice value.The nice values of processes can found under the column NI on issuing the command ps -el

 

Another value which decides the priority of a process is the real time priority value.It ranges from 0-99.The priority of a process is proportional to this value.The command ps -eo pid,rtprio lists the real time priority value of a process under the RTPRIO column.