Monday, 15 September 2014

learning export command

EXPORT

Signal

Various types of signals
SIGINT
is the interrupt signal. The terminal sends it to the foreground process when the user presses ctrl-c. The default behavior is to terminate the process, but it can be caught or ignored. The intention is to provide a mechanism for an orderly, graceful shutdown.

SIGQUIT
is the dump core signal. The terminal sends it to the foreground process when the user presses ctrl-\. The default behavior is to terminate the process and dump core, but it can be caught or ignored. The intention is to provide a mechanism for the user to abort the process. You can look at
SIGINT
as "user-initiated happy termination" and
SIGQUIT
as "user-initiated unhappy termination."

SIGTERM
is the termination signal. The default behavior is to terminate the process, but it also can be caught or ignored. The intention is to kill the process, gracefully or not, but to first allow it a chance to cleanup.


SIGKILL
is the kill signal. The only behavior is to kill the process, immediately. As the process cannot catch the signal, it cannot cleanup, and thus this is a signal of last resort.


SIGSTOP
is the pause signal. The only behavior is to pause the process; the signal cannot be caught or ignored. The shell uses pausing (and its counterpart, resuming via
SIGCONT) to implement job control.

Saturday, 13 September 2014

timers and task with Xenomai

Timer management services.

 Data Structures
• struct rt_timer_info
                         Structure containing timer-information useful to users.

Typedefs
• typedef struct rt_timer_info RT_TIMER_INFO
                       Structure containing timer-information useful to users.

Functions
• SRTIME rt_timer_ns2tsc (SRTIME ns)
                    Convert nanoseconds to local CPU clock ticks.

• SRTIME rt_timer_tsc2ns (SRTIME ticks)
                    Convert local CPU clock ticks to nanoseconds.
   
• RTIME rt_timer_tsc (void)
                    Return the current TSC value.

• RTIME rt_timer_read (void)
                    Return the current system time.

• SRTIME rt_timer_ns2ticks (SRTIME ns)
                   Convert nanoseconds to internal clock ticks.

• SRTIME rt_timer_ticks2ns (SRTIME ticks)
                    Convert internal clock ticks to nanoseconds.

• int rt_timer_inquire (RT_TIMER_INFO ∗info)
                    Inquire about the timer.

• void rt_timer_spin (RTIME ns)
                    Busy wait burning CPU cycles.

• int rt_timer_set_mode (RTIME nstick)
                    Set the system clock rate.





Task management service

Files
• file task.c
This file is part of the Xenomai project.

Functions
• int rt_task_create(RT_TASK ∗task, const char ∗name, int stksize, int prio, int mode)
Create a new real-time task.

• int rt_task_start(RT_TASK ∗task, void(∗entry)(void ∗cookie), void ∗cookie)
Start a real-time task.

• int rt_task_suspend(RT_TASK ∗task)
Suspend a real-time task.

• int rt_task_resume(RT_TASK ∗task)
Resume a real-time task.

• int rt_task_delete(RT_TASK ∗task)
Delete a real-time task.

• int rt_task_yield(void)
Manual round-robin.

• int rt_task_set_periodic(RT_TASK ∗task, RTIME idate, RTIME period)
Make a real-time task periodic.

• int rt_task_wait_period(unsigned long ∗overruns_r)
Wait for the next periodic release point.

• int rt_task_set_priority(RT_TASK ∗task, int prio)
Change the base priority of a real-time task.

• int rt_task_sleep(RTIME delay)
Delay the calling task (relative).

• int rt_task_sleep_until(RTIME date)
Delay the calling task (absolute).

• int rt_task_unblock(RT_TASK ∗task)
Unblock a real-time task.

• int rt_task_inquire(RT_TASK ∗task, RT_TASK_INFO ∗info)
Inquire about a real-time task.

• int rt_task_add_hook (int type, void(∗routine)(void ∗cookie))
Install a task hook.

• int rt_task_remove_hook (int type, void(∗routine)(void ∗cookie))
Remove a task hook.

• int rt_task_catch (void(∗handler)(rt_sigset_t))
Install a signal handler.

• int rt_task_notify (RT_TASK ∗task, rt_sigset_t signals)
Send signals to a task.

• int rt_task_set_mode (int clrmask, int setmask, int ∗mode_r)
Change task mode bits.

• RT_TASK ∗ rt_task_self (void)
Retrieve the current task.

• int rt_task_slice (RT_TASK ∗task, RTIME quantum)
Set a task’s round-robin quantum.

• ssize_t rt_task_send (RT_TASK ∗task, RT_TASK_MCB ∗mcb_s, RT_TASK_MCB ∗mcb_r,RTIME timeout)

Send a message to a task.

• int rt_task_receive (RT_TASK_MCB ∗mcb_r, RTIME timeout)
              Receive a message from a task.

• int rt_task_reply (int flowid, RT_TASK_MCB ∗mcb_s)
              Reply to a task.

• static int rt_task_spawn (RT_TASK ∗task, const char ∗name, int stksize, int prio, int mode,void(∗entry)(void ∗cookie), void ∗cookie)
             Spawn a new real-time task.

• int rt_task_shadow (RT_TASK ∗task, const char ∗name, int prio, int mode)
             Turns the current Linux task into a native Xenomai task.

• int rt_task_bind (RT_TASK ∗task, const char ∗name, RTIME timeout)
             Bind to a real-time task.

• static int rt_task_unbind (RT_TASK ∗task)
           Unbind from a real-time task.

• int rt_task_join (RT_TASK ∗task)
          Wait on the termination of a real-time task.

• int rt_task_same (RT_TASK ∗task1, RT_TASK ∗task2)
         Compare two task descriptors.


Friday, 12 September 2014

Xenomai coding

I have started playing with Xenomai

my first hello world code
//******************************hello.c***********************************************//
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_ALERT */
int init_module(void) {
printk("<1>Hello world 1.\n");
return 0;
}
void cleanup_module(void) {
printk(KERN_ALERT "Goodbye world 1.\n");
}
MODULE_LICENSE("GPL"); //To access Xenomai symbols
//*************************Makefile**************************************************//

obj-m           := hello.o
KDIR            := /lib/modules/$(shell uname -r)/build
PWD             := $(shell pwd)
EXTRA_CFLAGS    := -I/usr/xenomai/include -I/usr/include/

all:
        $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
        $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean

//**********************************************************************************//
-put proper taps or else it will show error
-after this I compile the code
$make
-there would be .ko file generated in the folder. after this load the module
$insmod hello.ko
$dmesg
$rmmod hello.ko
$dmesg
-check all the commands and see the changes in output

-I more code for testing
//********************************************************************************//
#include <native/task.h>

#define TASK_PRIO  99              /* Highest RT priority */
#define TASK_MODE  T_FPU|T_CPU(0)  /* Uses FPU, bound to CPU #0 */
#define TASK_STKSZ 4096            /* Stack size (in bytes) */

RT_TASK task_desc;

//
//you can use the cookie accordingly, as needed !!!
//
void task_body (void *cookie)

{
    //for (;;) {
    /* actual real-time code comes here */
    //}
}
int init_module (void)

{
    int err;
    err = rt_task_create(&task_desc,
                         "MyTaskName",
                         TASK_STKSZ,


                         TASK_PRIO,
                         TASK_MODE);
    if (!err)
        rt_task_start(&task_desc,&task_body,NULL);


}
void cleanup_module (void)
{

    //undo what you have done in init_module()

    rt_task_delete(&task_desc);
}
MODULE_LICENSE("GPL"); //To access Xenomai symbols

//********************************************************************************//
-We are done.Now in next post I would be working on timer API

enjoy........=) 



Xenomai installing on opensuse12.1


Steps to install Xenomai in opensuse12.1
1)create a separate directory under your home/working directory-say name
$mkdir /root/XENO_WS

2)download xenomai-2.6.3.tar.bz2 and linux-3.8.13.tar.bz2 packages from ftp/desdslides, to /root/XENO_WS- also download the required kernel configuration file,for the xenomai linux kernel

3)unpack both packages

4) cd xenomai-2.6.3/   (this folder containes source/headers for real-time kernel and
                        patches for the linux kernel to be used for Xenomai)

5) ./scripts/prepare-kernel.sh   \
    --linux=../linux-3.8.13  \
    --arch=x86  \
    --adeos=ksrc/arch/x86/patches/adeos-ipipe-<version>.patch  (select the appropriate <version>, for your linux kernel version)

Note : check the appropriate files are present and names are correct ??? - complete this step, with care

6) cd ../linux-3.8.13  (now, we have a patched kernel source for xenomai)


7) make mrproper
    make oldconfig

8) cp config-<forxenomai>  ( copying the custom configuration to the patched kernel directory )
eg:   $cp .config /boot/config-3.2.21-xenomai

//Edit the Makefile with your text editor and add -xenomai to
//the extraversion line.
$gedit Makefile



9) rest of the steps are the same as we did for a regular linux kernel -
       resume from   make oldconfig and complete all the steps !!!

10) reboot and load the newly built xenomai / linux kernel, which contains
    a patched linux kernel and the xenomai real-time nucleus+skins(microkernel + system APIs) !!!

11) now, your environment is ready for real-time coding in kernel space !!!

12) from here on, refer to class notes for xenomai and also refer to
    xenomai kernel module examples !!!

13) start understanding the examples and testing the examples - make sure
    you are comfortable with the examples and their working

14) next, start with assignment1 of Xenomai/RTOS - you need to refer to
    native_api.pdf and comments provided in the samples to understand
    the code/APIs

15) you can compile xenomai application modules, using just type make command
    from a specific example's folder(no arguments are needed) - make will use the Makefile provided
    in the respective sample folder - you can modify the Makefile, if
    needed !!! 

Notes :  /root/XENO_WS/xenomai-2.6.3/  is a directory holding xenomai kernel
         source code and headers !!! /root/XENO_WS/linux-3.8.13/ holds
         patched linux kernel source for xenomai !!!
        
         if there are any doubts, interact with the faculty, as needed !!!

         installation steps for part2 will be provided separately !!!
CAUTION:
THIS CONFIGURATION IS FOR KERNEL SPACE


//*****************************************************************************//

1) before starting the steps below, you must have installed the xenomai kernel space
   support, using the steps provided in part 1 - in addition, you must have completed
   testing samples for kernel space and also assignment1 of xenomai/RTOS

2) if you have completed the above, cd /root/XENO_WS/ folder

3) mkdir /root/XENO_WS/XN_BUILD and cd /root/XENO_WS/XN_BUILD

4)  /root/XENO_WS/xenomai-2.6.3/configure  --enable-x86-sep  (this is will prepare for building and installing
                                   user-space components of xenomai / RTOS)
-------------------------------------------------------------------------------
note : there is no need for any configuration file, for building this part !!!
-------------------------------------------------------------------------------
5) make ( to build the user-space components - mainly xenomai RT libraries)

6) make install (to install scripts and libraries for xenomai )

7) now, the user-space installation and scripts are installed under /usr/xenomai

8) next, read class notes related to user-space real-time tasks and rules !!!

9) now, try to test user-space examples provided - explore the Makefile provided
   for such examples - they will provide information in libraries used and
   headers used - you may need to modify sample Makefile(s) to your requirements !!!

10) once you are comfortable with user-space samples, you can switch to assignment2 of
   xenomai/RTOS !!!


Note: user-space real-time tasks are subject to primary mode <-> secondary mode switching !!!
CAUTION:
THIS CONFIGURATION IS FOR USER SPACE
//********************************************************************************//

Tuesday, 9 September 2014

Multi_threading in c linux(opensuse)

How To make your program mulch-processing or multi-threading:

This question made me curious so I started to dig around this.I first read articals from internet and I found it quit easy.But has always when I implemented it ,it took lot time to for getting actualy my code running.In this blog I will let you know problems that I faced but first let us start with theory of threads.I am making notes from advance-Linux-programming book.

Thread:
-Threads are like process,a mechanism to allow a program to do more than one thing at a time
-A thread is sometimes referred to as a lightweight process.A thread will share all global variables and files descriptor of the parent process which allows the programmer to separate multiple tasks easily within a process.
-Advantage of using thread is that they will automatically take advantage of machine with multiple processors
-using mutiple threads will also use fewer system resources compared to forking a child process to handle a connection request
-A thread shares most of its resources with the parent process,so a thread will use fewer resources than a process would
-it shares everything except it has its own program counter,stack and registers
-however static variable inside the thread will be shared between threads.
   Thread Creation:
-Each thread in a process is identified by a thread ID

int pthread_create(pthread_t *tid,
   const pthread_attr_t *attr,
   void *(*func)(void *), void *arg)
 


1. A pointer to a pthread_t variable, in which the thread ID of the new thread is
stored.
2. A pointer to a thread attribute object.This object controls details of how the
thread interacts with the rest of the program. If you pass NULL as the thread
attribute, a thread will be created with the default thread attributes.Thread
attributes are discussed in Section 4.1.5, “Thread Attributes.”
3. A pointer to the thread function.This is an ordinary function pointer, of this
type:
void* (*) (void*)
4. A thread argument value of type void*. Whatever you pass is simply passed as
the argument to the thread function when the thread begins executing.

-Thread can be exited in two ways
1)is by returning from the thread function
2)Alternately, a thread can.
exit explicitly by calling pthread_exit.

Monday, 8 September 2014

Character drivers for linux

Character device driver
Today we will go thought character device driver. I am reading linux device driver(LDD) book and noting points in this blog.I will also present simple and miscellaneous codes on to this blog.If you find this theory portion boring you can skip it and move directly to practical side of blog. But I recommend to read the theory portion if you are new to this subject.

-Mainly there are three types of device drivers
1)char:to transfer stream of bytes
2)block:to transfer data in blocks of data.block size can be 512 or more in power of 2
3)network:they are used for network protocol

-Great thing of linux is every thing is file in linux. So character drivers are also files.So you can manipulate this file and control the device. This files are known as device file. They are present in /dev/char
$ls -l /dev/char
    this would give you all device file

- Each device file are represented my major number and minor number
 When a device file is opened, Linux examines its major number and forwards the call to the driver registered for that device.

The Internal Representation of Device Numbers
Within the kernel, the dev_t type (defined in <linux/types.h>) is used to hold device
numbers—both the major and minor parts.
MAJOR(dev_t dev);
MINOR(dev_t dev);

If, instead, you have the major and minor numbers and need to turn them into a dev_t, use:
MKDEV(int major, int minor);
A device file is a special file. It can’t just be created using cat or gedit or shell redirection for that matter.
mknod path type major minor

chmod flag path   //used to give mode

Allocating and Freeing Device Numbers
Now we have to register device
int register_chrdev_region(dev_t first, unsigned int count, char *name);
-first is the device number to the first device,then comes count that is total number of continuous devices,then it gives name to our file.Name would be visible in
 /proc/devices and sysfs.


-You should know your major number and minor number to use this API
-If this API returns 0 then it means device is succefully register


-If you dont know which major number to assign then there is know API which gives major number dynamically.
 int alloc_chrdev_region(dev_t *dev, unsigned int firstminor,unsigned int count, char *name);


-To free memory  use this API
void unregister_chrdev_region(dev_t first, unsigned int count);

-disadvantage for dynamic allocation is that it cant create device node in advance 
-above API only gives number to your driver.It does not connect your driver.So we will learn now how to connect driver

Some Important Data Structures
1)struct file_operations,
2)struct file,
3)struct inode

1)File Operations
Conventionally, a file_operations structure or a pointer to one is called fops

struct module *owner
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*aio_read)(struct kiocb *, char __user *, size_t, loff_t);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_write)(struct kiocb *, const char __user *, size_t, loff_t *);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *, int);
.
.
.
there many such structures in file operation
this is example how file operation.More clearity will come when you check the code for char driver 
struct file_operations scull_fops = {
.owner =THIS_MODULE,
.llseek =scull_llseek,
.read =scull_read,
.write =scull_write,
.ioctl =scull_ioctl,
.open =scull_open,
.release = scull_release,
};

2)file structure(struct file)
-struct file, defined in <linux/fs.h>

-The file structure represents an open file

field of file structure are
-mode_t f_mode;The file mode identifies the file as either readable or writable (or both), by means of the bits FMODE_READ and FMODE_WRITE
-loff_t f_pos:The current reading or writing position
-unsigned int f_flags-These are the file flags, such as O_RDONLY, O_NONBLOCK, and O_SYNC. O_NONBLOCK is mostly used
-struct file_operations *f_op-The operations associated with the file.
-void *private_data;
-struct dentry *f_dentry;


3)inode structure
The inode structure is used by the kernel internally to represent files.
dev_t i_rdev;
For inodes that represent device files, this field contains the actual device number.
struct cdev *i_cdev;
struct cdev is the kernel’s internal structure that represents char devices; this
field contains a pointer to that structure when the inode refers to a char device
file.
 -this macro are used to get major number and minor number from inode of device file
unsigned int iminor(struct inode *inode);
unsigned int imajor(struct inode *inode);
this should be used instead of using i_rdev

We are done with data structure.Now we move forward for char device registration 
-struct cdev is used to represent char device present in <linux/cdev.h>

-There are two ways of allocating and initializing one of these structures

1)This is at runtime
struct cdev *my_cdev = cdev_alloc( );
my_cdev->ops = &my_fops;


2)void cdev_init(struct cdev *cdev, struct file_operations *fops);
-finally when cdev structure is set up now its time to tell kernel with this API
int cdev_add(struct cdev *dev, dev_t num, unsigned int count);
-as soon as cdev_add returns, your device is “live” and its operations
can be called by the kernel.
-To remove a char device from the system, call:
void cdev_del(struct cdev *dev);

-For completeness, we describe the older char device registration interface.Classic way to register device
int register_chrdev(unsigned int major, const char *name, struct file_operations *fops);
name is name of driver that reappears in /proc/devices 
int unregister_chrdev(unsigned int major, const char *name);

cdev_init() - used to initialize struct cdev with the defined file_operations
cdev_add()  - used to add a character device to the system. 
cdev_del()  - used to remove a character device from the system
After a call to cdev_add(), your device is immediately alive. All functions you defined (through the file_operations structure) can be called.




Note:
struct cdev is one of the elements of the inode structure. As you probably may know already, an inode structure is used by the kernel internally to represent files. The struct cdev is the kernel's internal structure that represents char devices. So this field is a pointer to that structure while the inode refers to the char device file. Therefore if the kernel has to invoke the device it has to register a structure of this type.
some commands(let chardev be our device file)
ls -l /dev
mknod /dev/chardev 60 0
echo "jay kothari">/dev/chardev
cat /dev/chardev
modinfo (driver name)
lsmod | grep (driver name)


With this we compete the registration of char device


Practical:
 Now lets try to load a character driver for number of devices:
 step1:
-go to
$sudo cd /usr/src/linux-(version)/drivers/char
$mkdir (folder name)
$cd (folder name)
$vi (file name).c
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//
#include <linux/init.h>       
#include <linux/module.h>
#include <linux/kernel.h>

#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
/*    fs/char_dev.c, drivers/base/class.c
 *    drivers/base/core.c
 */
#include <linux/slab.h>
#include <linux/kfifo.h>

#define MAX_SIZE 4096

int ndevices=5;
module_param(ndevices,int,S_IRUGO);

typedef struct private_object
{
    struct cdev cdev;
    unsigned char* pbuf;
    struct kfifo kf1;
    struct list_head lentry;
}C_DEV;
LIST_HEAD(phead);
dev_t pseudo_dev_id;

struct class *pseudo_cls;


//******************************************open()**************************************************************//
static int pseudo_open(struct inode *inode,struct file *file)
{
     C_DEV* probj=container_of(inode->i_cdev,C_DEV,cdev);
    printk("pseudo open method\n");
    file->private_data=probj;
    return 0;
}
//close(fd);
static int pseudo_release(struct inode *inode,struct file *file)
{
    printk("pseudo close method\n");
    return 0;
}
//****************************************read()******************************************************************//
static ssize_t pseudo_read(struct file *file, char __user *ubuf,size_t count, loff_t *ppos)
{
    unsigned char* tbuf=kmalloc(count+1,GFP_KERNEL);

    C_DEV* pdev=file->private_data;
    int len=kfifo_len(&pdev->kf1);

    int ret,nbytes;
    printk("pseudo read method entered\n");
   
    if(count>len)
        count=len;//min(count,length)//
    if(count==0) return -EAGAIN;
   
    nbytes=kfifo_out(&pdev->kf1,tbuf,count);
    printk("read:nbytes=%d\t,count=%d\t,off=%d\t,kfifo length=%d\n",nbytes,count,*ppos,kfifo_len(&pdev->kf1));
    tbuf[nbytes]=0;
    printk("read:tbuf=%s\n",tbuf);
    ret=copy_to_user(ubuf,tbuf,nbytes);
//    printf("tbub%s\n",*tbuf);
    printk("read::ret=%d\n",ret);
    if(ret) return -EFAULT;
//    *ppos += nbytes;
    kfree(tbuf);
    return nbytes;
}
//*****************************************************************************************************************//
//**********************************write()***********************************************************************//
static ssize_t pseudo_write(struct file *file, const char __user *ubuf,size_t count, loff_t *ppos)
{
    C_DEV* pdev=file->private_data;
   
    int nbytes;
   
    int remain=kfifo_avail(&pdev->kf1);
    unsigned char* tbuf=kmalloc(count,GFP_KERNEL);

    printk("write:pseudo write method entered,remain=%d\n",remain);
    if(remain==0)
        return -EAGAIN;
    if(count > remain)
        count=remain;    //min(count,remain)
   
    if(copy_from_user(tbuf,ubuf,count))
        return -EFAULT;
      nbytes=kfifo_in(&(pdev->kf1),tbuf,count);

   
    printk("nbytes=%d\t,count=%d\t,off=%d\t,kfifo length=%d\t",nbytes,count,*ppos,kfifo_len(&pdev->kf1));
//    *ppos += nbytes;
    kfree(tbuf);
    return nbytes;
}
//*****************************************************************************************************************//
//*************************************file operation**************************************************************//
static struct file_operations pseudo_fops=
{
    .open=pseudo_open,
    .release=pseudo_release,
    .read=pseudo_read,
    .write=pseudo_write,
    .owner=THIS_MODULE,
    //.ioctl.pseudo_ioctl
};
//******************************************************************************************************************//

//*********************************************init function()*****************************************************//
static int pseudo_init(void)   
{
    int ret,i=0;
    C_DEV* pdev;     //struct private_object* pdev;
    ret=alloc_chrdev_region(&pseudo_dev_id,0,ndevices,"pseudo_char_driver");
    if(ret<0)    return -EFAULT;
    printk("driver registered,major=%d\n",
            MAJOR(pseudo_dev_id));
    pseudo_cls=class_create(THIS_MODULE,"pseudo_class");
    //per device initialization
    for(i=0;i<ndevices;i++)
    {
     pdev=kmalloc(sizeof(C_DEV),GFP_KERNEL);
     pdev->pbuf=kmalloc(MAX_SIZE,GFP_KERNEL);
     kfifo_init(&(pdev->kf1),pdev->pbuf,MAX_SIZE);
    // kfifo_alloc(&pdev->kf1,MAX_SIZE,GFP_KERNEL);//*
     cdev_init(&pdev->cdev,&pseudo_fops);
     kobject_set_name(&(pdev->cdev.kobj),"my_pseudo_dev%d",i);
     ret=cdev_add(&pdev->cdev,pseudo_dev_id+i,1);
     if(ret<0)
    {
        printk("cdev_add failed\n");
        kfifo_free(&pdev->kf1);
        //unregister the driver
        return -EFAULT;
    }
    list_add_tail(&pdev->lentry,&phead);
    device_create(pseudo_cls,NULL,pseudo_dev_id+i,NULL,"pchardev%d",i);
    printk("device initialized:%d\n",i);
        }
        printk("Pseudo Char Driver registered successfully\n");
        return 0;
}
//*****************************************************************************************************//
//*****************************************exit*******************************************************//
static void pseudo_exit(void)   
{
    struct list_head *ptemp,*qtemp;
    C_DEV* pdev;
    int i=0;
    //per device cleanup/deallocation
    list_for_each_safe(ptemp,qtemp,&phead)
    {
        pdev=container_of(ptemp,C_DEV,lentry);
        kfifo_free(&pdev->kf1);
        cdev_del(&pdev->cdev);
        kfree(pdev);
        device_destroy(pseudo_cls,pseudo_dev_id+i);
        printk("cleaned device:%d\n",i);
        i++;
    }

    class_destroy(pseudo_cls);
    unregister_chrdev_region(pseudo_dev_id,5);

    printk("Pseudo Char Driver:Bye\n");   
}
//********************************************************************************************************//

module_init(pseudo_init);
module_exit(pseudo_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jay Kothari");
MODULE_DESCRIPTION("driver for n number of device");

//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//

-step 2:
make a Makefile in this same folder as follwing
$vi Makefile 

obj-m += (file name).o
all:
      make -C /lib/modules/$(shell uname -r)/build M=${PWD} modules
clean:
      make -C /lib/modules/$(shell uname -r)/build M=${PWD} clean

-step 3:
Now compile using make
$make
 $ls
check .ko file is generated?

-step4
now load the module to the kernel using insmod command
$insmod (file name).ko

-step 5:
now go to user space /home director
then make a folder
$mkdir(folder name)

-step6:
write a c program that all the char device file
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//
#include<stdio.h>
#include<fcntl.h>
#include<assert.h>
#include<string.h>

int main(int argc,char *argv[])
{
    assert(argc>1);
    char buf[100];
    char i=0;
    memset(buf,0,100);
    printf("Input:%s\n",argv[1]);

    int fd=open("/dev/pchardev3",O_RDWR);
    if(fd<0)
    {perror("open error");
    exit(3);
    }
    int k;
      k= write(fd,argv[1],strlen(argv[1]));
        if(k<0)
    {perror("write");
        exit(2);
    }
   
         printf("write is done\n");
                k= read(fd,buf,100);
         if(k<0) {
             perror("read");
             exit(1);
         }  
         buf[k]='\0';
         printf("%s\n",buf);

        printf("%s\n",buf);
        return 0;
}
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//

-step 7:
make compile this in user space and run it
gcc -(file_name).c -o (file_name)
./(file_name) "JAY KOTHARI"


//------------------------------------------------------------------------------------------------------------------//

-There a code for single character driver that i found from net you can check it out as I used it as my reference code to make this code.Haven’t change authors name to give him honor and I am thankful to him.

  • #include <linux/kernel.h>
  • #include <linux/module.h>
  • #include <linux/moduleparam.h>
  • #include <linux/init.h>
  • #include <linux/slab.h>
  • #include <linux/fs.h>
  • #include <linux/fcntl.h>
  • #include <linux/stat.h>
  • #include <linux/types.h>
  • #include <linux/errno.h>
  • #include <asm/system.h>
  • #include <asm/uaccess.h>
  •  
  • #define DEVICE_NAME "chardev"
  • #define BUFFER_SIZE 1024
  •  
  • MODULE_LICENSE("Dual BSD/GPL");
  • MODULE_AUTHOR("Zobayer Hasan");
  • MODULE_DESCRIPTION("A simple character device driver.");
  • MODULE_SUPPORTED_DEVICE(DEVICE_NAME);
  •  
  • int device_init(void);
  • void device_exit(void);
  • static int device_open(struct inode *, struct file *);
  • static int device_release(struct inode *, struct file *);
  • static ssize_t device_read(struct file *, char *, size_t, loff_t *);
  • static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
  •  
  • module_init(device_init);
  • module_exit(device_exit);
  •  
  • static struct file_operations fops = {
  • .read = device_read,
  • .write = device_write,
  • .open = device_open,
  • .release = device_release
  • };
  •  
  • static int device_major = 60;
  • static int device_opend = 0;
  • static char device_buffer[BUFFER_SIZE];
  • static char *buff_rptr;
  • static char *buff_wptr;
  •  
  • module_param(device_major, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
  • MODULE_PARM_DESC(device_major, DEVICE_NAME " major number");
  •  
  • int device_init() {
  • int ret;
  • ret = register_chrdev(device_major, DEVICE_NAME, &fops);
  • if(ret < 0) {
  • printk(KERN_ALERT "chardev: cannot obtain major number %d.\n", device_major);
  • return ret;
  • }
  • memset(device_buffer, 0, BUFFER_SIZE);
  • printk(KERN_INFO "chardev: chrdev loaded.\n");
  • return 0;
  • }
  •  
  • void device_exit() {
  • unregister_chrdev(device_major, DEVICE_NAME);
  • printk(KERN_INFO "chardev: chrdev unloaded.\n");
  • }
  •  
  • static int device_open(struct inode *nd, struct file *fp) {
  • if(device_opend) return -EBUSY;
  • device_opend++;
  • buff_rptr = buff_wptr = device_buffer;
  • try_module_get(THIS_MODULE);
  • return 0;
  • }
  •  
  • static int device_release(struct inode *nd, struct file *fp) {
  • if(device_opend) device_opend--;
  • module_put(THIS_MODULE);
  • return 0;
  • }
  •  
  • static ssize_t device_read(struct file *fp, char *buff, size_t length, loff_t *offset) {
  • int bytes_read = strlen(buff_rptr);
  • if(bytes_read > length) bytes_read = length;
  • copy_to_user(buff, buff_rptr, bytes_read);
  • buff_rptr += bytes_read;
  • return bytes_read;
  • }
  •  
  • static ssize_t device_write(struct file *fp, const char *buff, size_t length, loff_t *offset) {
  • int bytes_written = BUFFER_SIZE - (buff_wptr - device_buffer);
  • if(bytes_written > length) bytes_written = length;
  • copy_from_user(buff_wptr, buff, bytes_written);
  • buff_wptr += bytes_written;
  • return bytes_written;
  • }
  •  
  • /*
  • End of Source Code
  • */


  • And you are done......enjoy......its easy so smile
    what you need to do if you dont understand the code is that you google out each API you find and you would be done

    Still if there are any troubles then let me know
    Thank you

    Bibliography:
    -read chapter 3 of linux device drivers
    -http://zobayer.blogspot.in/2011/07/simple-character-device.html
    -http://www.makelinux.net/ldd3/chp-3-sect-4