Sunday, 28 September 2014

Lecture notes


Lecture notes:
*what is relation of kernel and modules?
Ans-registration,methos,data structure,objects etc
*How do you use api without library
ans symbol table
*what is use of symbol
ans address of data or function
*difference between user space and system space
ans rules are different

image


FRAMEWORKS
-platform subsys
-usb subsys
-LLDM or Device model
-sysfs
-RTOS device model
-RTOS driver model

libraries->system call->VFS->char->my driver model->device
-----------
userspace

*OS concepts
-ISR -process schedulling
-IPC
-wake-up
-device model plays important role in embedded kernel

DERIVERS
-mainly there are three types of device drivers
1)character 2)block 3)network

-Porting involves customization of RTOS for specific board which may involve adding,integrating new set of device drivers.

EOS atch/implementation
-RTOS------->real time,embedded}they can be connected
-Embedded linux--------->
+specific bootloader
+HAL will be very specific
+BSP is very specific
+booting technique is very specific
+custom lib.



MEMORY SPACE

-virtual address space---->page table------->physical address
(memory management)
KERNEL MEMORY MANAGER
-memory allocator
1)buddy allocator
-buddy allocator per zone of physical memory
-each buddy allocator has serveral levels
-each level manages true memory
-memory blocks are multiples of page size according to level each block of true memory
-using ptr to struct page we must pass it to kmap() in the case of low memory region,kmap() will extract the corresponding KVAS address
-using ptr tp struct page we must pass it to kmap() will allocate a KVAS page from KVAS
-kumap is must to use for each page frame.

Limitations:
-it provids multiple off page frames
-minimal granulity-internal fragmentation
-it only provides multiple off page frames.-external fragmentation.

2)non-config allocator
--vmalloc() the API interface
-we may request a size of a single page memory or multiple of page size memory block
-non-config memory allocation will do the following
-allocate one or more page frames,from high memory region
-allocates one or more kvas pages from VMALLOC region!!
-using the kvas pages,map the allocated page frames!!
-kvas pages are strictly contiguous and page frames are not contiguous
-in addition VMALLOC region is also used to map memory space redistor of controller is requestby device drivers once mapped logical|virtual address of VMALLOC region are used by drivers!!!
3)slab allocator
-slab allocator subsystem manage serveral slab cache allocator!!
-each slabcache allocator is provided to support memory docs of specific size or type of object.MOst slab cache allocator provides memory blocks or objects less than a page size.
-system creates serveral slab cache allocator each providing support for allocation of specific system object.
-these slab cache allocator can be used by relevant subsystem or componets
-however the slab cache allocator be used by device or other external componets
-system provides seperate slab cache allocator for device drivers or other external componets
-such generic slab cache allocator can be accessed using kmalloc api
-for eg.kmalloc(size,GFP_KERNEL)
-in the case if OBJECTA,system will round_up the size field to the nearest size slab cache allocator
-each size_n slab cache allocator is manager using a slab cache descriptor.
-each slab cache descriptor manage one or more slab!! each slab is typically
a single page frame or multiple contiguous frame.
-each slab is managed by a slab descriptor.
-each slab contains one or more objects of size.


Image 2


DEVICE MODEL
-several objects repreasenting devices.
-contains hierarchy
-contains several datastructures
-device model is built on top of several objects
-some of these are low,intermediate and high level objects
-all these objects are connected and worked together
some low level objects are
-kobjects,kset,kobj_type_attribute object,many more

-struct kobject is the most primitive object that manage a logical device or a physical device
-following are some of the characterics of kobject
1)It maintains the respective device in a herarchy
2)it maintains usage/refrence count of the respective device
3)it maintains the respective device in an aggregation
4)it enable a device to be connected to sysfs
Kset
-kset object may be used for aggregation a set of kobjects
-kobjects of a kset may also be involved in managing hierary
Kobj-type
-it is another used along with a kobject it does the following
-it enables a destination for the kobject and the respective device
-it enables the sysfs to interact with device attributes
-when we manage kset we do with kobject.
-kset can be used to manage multiple device

module----->device model---------->sysfs
-

FILE SYSTEM
-in memory
-on disk memory

-the sysfs manages and maintains metadata only in memory not on-disk
-In sysfs,a typical directory file or a regular file or a softlink are represented using sysfs_dirent object
-typically for a given kobject when a konject is registering with device model a sysfs directory file
vi fs/
-the kobject and corresponding sysfs_divert are connected to each other.
-a given kobject can have one or more attributes
-attributes are represented by struct attributes objects which are abstact
-however such abstract attributes can be associated with real attributes of physical or logical device represented by Kobject.
-In addition such attributes objects can be associated with high level attributes objects these high level attributes object will support certain methods which can be usefull
-corresponding to each attributes of a kobject there will be a sysfs regular file created under sysfs directory of the kobject
-these sys fs are children of the sysfs directory of the kobject and all these children are siblings of the same level.
-the sysfs_dirent object of an attributes as an pointer pointing toa corresponding struct attributes
-in addition,sysfs_dirent of an attribute also as pointer to sysfs_dirent of the kobject meaning parent sysfs_dirent
-let us assume we want to access a sysfs file(regular file)corresponding to an object of a device(its kobject)
vi fs/sysfs/file.c
sysfs----->kobject
sysfs------>attribute

-kobjects does not define device
another harware entity
driver_struct----->driver()
device_struct----->device()
-certain has resources detail
-blocking | wake-up
-certain loading

-assuming we have registred out platform device,if a matching/compatible driver is loaded into the system,following actions will be taken
-probe() method ,following action are typically done
-collect resources into of the specific device lock the resources
-allocates other objects buffers!!
-In addition we may have to register certain system objects with other frameworks
-we must lock the IO space or memory space or IRQ resources drivers as per rules
-to lock IO space addresses we must use request_mem_region()
-to free we may use release_region() or release_mem_region() respective
-in the case of memory space register addresses IO remap must be used to allocate and map into KVAS
-In the prob() once the basic set_up is done,we must register with another functional frame-work!!!
-Such a functional work may be a char layer or a block layer or a network layer or a RT device layer or some layer!!

Application--->RTOS interface----->RTOS kernel------>RTDM layer----->RTDM driver----->platform driver----->platform device----->platform layer------>HAL

INTRODUCTION TO SLEEPING
-if a driver method is invoked in a process context or a kernel thread context
-driver method may block the current process or kernel thread,if there are no contrains
Constrain
-if a spin-lock is up currently behold by the driver method
-if premption is disabled by the driver method
-if local has interrupts are disable by driver method
-a typical driver may maintain one or more weight queues per device in the private object!!
-however rules are different
-we must use a approval lacking mechanizm as per execution
-we may use spinlock(without disabling interrupts),if the critical section are in process context!!
-when a spinlock is acquired implicitly premption is disable
-we may use mutext if the critical section are in process context one reason may be that critical section are relative longer.
-we must use spinlocks (with interrupts disabling) if critical section are between process context and interrupt context in this case ,spinlock(with int disabling) must be done, in process contexts!!
-as per rules when code executes in one of the above critical section blocking is disallowed!!
-as per kernel language such critical section are said to be atomic context


USB DEVICE
-logical description of an USB device and its charateritics
-Their logical description|picture|characteritics is used by operating system to manage and interact with an USB device!!
-such a logical model is defined by USB specification and mainly for interfacing with os or firmware!! This logical model is very intelligent!!
-A typical USB bus is sourced by a host controller and its root-hub!!
-Host controller is typically resisdent on a less intelligent bus or a more intelligent PCI bus!!
-which means,host controller will be managed by a platform driver or a PCI driver
-In addittion Host controller will be further manage for I/O using a host controller driver
-Root-hub is a logical device of host controller manager by a Hub driver.
-In addition each USB device is treated as physical USB device containing one or more logical USB device. In most case only one logical device is present
-each USB device is manage using the USB physical device driver and one or more corresponding USB logical device drivers.Such logical device or custom drivers!!
-Each USB hub is managed using the USB physical device driver and the hub driver.
-The hub driver manages hub functionality in this context!! Hub driver plays a very important role in device management of USB bus
-A typical USB device is described by the following description implementation by the device firmware
-A device descriptor is used to describe overall charateritics of the device
-A device descriptor represents the physical USB device
-Every USB device may have one or more configuration descriptor
-A configuration descriptor defines power requirement and number of logical device support under the configuration !!
-During operation OS/USB framework will select a configuration may be modified explicitly if needed
-Assuming a configuration is selected it will support one or more interface descriptor each interface descriptor describes one logical device.
-Each logical device may contain one or more end points descriptor
-Each endpoint descriptor manages an endpoint of logical device -an endpoint may be a control endpoint or an IN endpoint or an OUT endpoint
-Every USB device as common controller endpoint known as endpoint o_default control endpoint.
-These descriptor are read/extracted by os/usb frame work ,when an usb device discovered or configured
-Each USB physical device is assigned a dynamic USB device number.This USB device number is unique for a device within usb bus.The range is 1 to 127 is -o is reserved for special address.
-Each endpoint also has an address.This includes endpoint number and endpoint direction.
-During the IO transfer USB framework and driver need to access endpoint descriptor
-To access a specific endpoint of a logical USB device of a physical USB device USB dev number and endpoint address is used
-Hub device plays an important role in device discovery and configuration.
-typically A hub device has a logical hub device .this logical hub device contain a controll end point and an interrupt end point.
-Interrupt end point provides HUB ports status change information
As per hub driver frame work int end points of all the hubs are polled periodically!!
-To do this polling USB frame work /hub driver use an interrupt URB!!In the case of interrupt URB,USB frame work will periodically generate URB request.If there is negative response ,USB request will continious
-If the response is +ve ,another polling must be initiated
-If there is +ve response the URB response is proccessed by kernel thread is woken up when needed other wise in blocked state!!
-This kernel thread continious processing the URB response if new device is connected it will be discovered and configured!!
-Descriptor are read and charactertics are understood
-Usb dev number must be assigned and configured selected
-default control end point
-an usb device is identified using info. Stored in its device descriptor and other descriptor
-in this info commonly used for idebtification is the vendor|product combination anf this combination is not used to bind physical device but used to bing logical device.
-this combination informatiojn is also encoded in the logical device driver
-struct usb_device_id{} is an object used to define supported device by the logical device driver!!
-struct usb_driver{} is allocated and initialized to repreasent an usb physical device
-struct usb_interface object represents an usb logical device .It is also connected to other objects!!
-struct usb_bus() represents an usb bus!!
-this usb_bus() object manages a tree of struct usb_device() object!!
-struct usb_hcd() -it is a superset of struct usb_bus() object!!
-struct hc_driver represents host controller driver . A pointer from USB_HCD() points to this struct hcd_driver
-struct usb_hub() repreasents a usb hub!!!
-this objects internally connects to struct usb_device of the corresponding hub_device
-struct hub_driver() is the object that represents the usb hub driver of the system
-let us typically start with usb_hub_init()
-USB_hub_init() is invoked from usb_init()
-A new kernel thread knows khubd is creaded
-khubd is associated with hub_thread()
-hub_thread() blocks and wake-up when needed when woken-up by hub driver /usb frame work
-hub_event() is the important method executed by hub_thread!
-In the hub driver the prob() method is used when a new hub us detected and the hub driver binds to the logicall devicve of the hub!!
-further invokes hub_configure()!!
-hub_configure set up an interrupt URB for the hubs interrupt end point
-hub_configure also submits the interrupt URB with the USB subsytem
-when the interrupt URB is submitted a compition handler is alsoi submitted a completion handler is a call back which will be invoked by USB frame work

There is response from the hub
-the call back method is known as hub_irq()!!it executes in interru context!!
-Hub_irq does the following action
-collects hub statyus changes went bits-stone it as part of start
RT message queues
-message queues buffer is determinitally allocated and memory
-send/receive API provides strict time-out parameter!!
image 3

GPOS RTOS
-memory protection -No memory protection
problem 1)No overhead
1)overhead 2)smaller foot print
2)footprint

Virtual machine---->physical memory manager----->provides high latency as its api are not designed for real time

RTOS scheduling policy
-typical real time PRIO based
-priority(number of priority are configurable)
-RT RR scheduling will also be supported.

-In a given implementation RR may be enabled or disabled while in free RTOS RR will be enabled if config USE_PREMPTION is
-RT task typically a given RT task will be assigned RT PRIO scheduling policy or RT policy!!
-In addition using certain system API we may provide peridic scheduling as per this our periodic task will woken-up as per period.
-When our RT task is woken-up it will be scheduled as per scheduling policy and priority
-Interrupt priority are higher than task priority
Intrrupt priority
-high dependent on port architechture
-0 is hightest and 31 is lowest
-possible interrupt priority are 0-31
-ISR with interrupt priority 5-31 may use ISR safe API
-ISR with interrupt priority ve 5 cannot use safe API
-interrupt and ISR support nesting and priotization
-RTOS API may disable harware interrupt to implement critical section code
-however they are highy port specific
-such hardware interrupts to disabling must be subject to timing contrains
-sharing interrupts is not accepted in RTOS
-In addition we pass parameter to API the current state of woken up task
-if a higher priority task is woken up and scheduler is invoked it will complete a task switching otherwise not now!!
-In the case of free_RTOS,instead of software generation interrupts is used!! this software generated interrupts is of lowest interrupts priority
-When this interrupts is service it ISR is serviced.This ISR will invoke scheduler

How does BSP differs from port layer
-Port will be modified if we move to another Arch.(port layer is HAL)


Zenomai:-
-Is a typically linux kernel suitable for hard real time os
-Still developers need real time linux a linux based RTOS!! developer using embedded linux-based
-A real-time linux + embedded linux-based
-one such real time linux implementation is know as RT-LINUX
-Another such real time linux is xenomai
-In real time linux implementation a deterministic and low latency interrupts management framwork is added using a micro-kernel or nano kernel to kernel space such a microkernel or nano kernel coexits with linux kernel but takes primary control of hardware of the system!!
-In addtion such a real time system also provides other deterministic and low latency services using a micro-kernel!!
-real time managed under this microkernel will provide real time performance
-linux kernel continious to provide non-rt services as before!!
Xenomai contains
-Task Managment
-Memory management
-IPC feature
-kernel space
userspace
-real time task may have rt task or non rt task
-user space non-rt task is managed using pd
-A userspace rt task is manged using pd and TCB
-A typical non-rt task of user space is managed using Pd and linux scheduler
-A typical RT-task of user space is manged using TCB when rt-task is executing in primary mode of xenomai envitoment
-rt task will keep on execting in primary mode until linux system call is not invoked
-Typically ono rt task is used in user space for initialization and diagnostics!!
-in xenomai rt_pipe and rt_queues are created with predefined size
-the size allocated this rt heap with the pipe/queue
-whenevr buffer is needed for rt pipe or rt queue we must allocate buffer from respective heap.Once used we must free respective buffer.


Wednesday, 24 September 2014

Memory Layout of C Program - Code, Data, .BSS, Stack, and Heap Segments

Memory Layout of C Program

Before talking of memory layout of a C program and its various segments to store data and code instructions we should first understand that a compiler driver (that invokes the language preprocessor, compiler, assembler, and linker, as needed on behalf of the user) can generate three types of object files depending upon the options supplied to the compiler driver. Technically an object file is a sequence of bytes stored on disk in a file. These object files are as follows:
  • Relocatable object file: These are static library files. Static linkers such as the Unix ld program take collection of relocatable object files and command line arguments as input and generate a fully linked executable object file as output that can be loaded into memory and run. Relocatable object files contain binary code and data in a form that can be combined with other relocatable object files at compile time to create an executable object file.
  • Executable object file: These are executable files contain binary code and data in a form that can be copied directly into memory and executed.
  • Shared object file: These special type of relocatable object files are loaded into memory and linked dynamically, at either load time or run time.

Object files have a specific format, however this format may vary from system to system. Some most prevalent formats are .coff (Common Object File Format), .pe (Portable Executable), and elf (Executable and Linkable Format).

Code and Data Segments

However, the actual layout of a program's in-memory image is left entirely up to the operating system, and often the program itself as well. This article focus on the concepts of code and data segments of a program and does not take any specific platform into account. For a running program both the machine instructions (program code) and data are stored in the same memory space. The memory is logically divided into text and data segments. Modern systems use a single text segment to store program instructions, but more than one segment for data, depending upon the storage class of the data being stored there. These segments can be described as follows:
1. Text or Code Segment
2. Initialized Data Segments
3. Uninitialized Data Segments
4. Stack Segment
5. Heap Segment

Text or Code Segment

Code segment, also known as text segment contains machine code of the compiled program. The text segment of an executable object file is often read-only segment that prevents a program from being accidentally modified.

Data Segments

Data segment stores program data. This data could be in form of initialized or uninitialized variables, and it could be local or global. Data segment is further divided into four sub-data segments (initialized data segment, uninitialized or .bss data segment, stack, and heap) to store variables depending upon if they are local or global, and initialized or uninitialized.

Initialized Data or Data Segment

Initialized data or simply data segment stores all global, static, constant, and external variables (declared with extern keyword) that are initialized beforehand.

Uninitialized Data or .bss Segment

Contrary to initialized data segment, uninitialized data or .bss segment stores all uninitialized global, static, and external variables (declared with extern keyword). Global, external, and static variable are by default initialized to zero. This section occupies no actual space in the object file; it is merely a place holder. Object file formats distinguish between initialized and uninitialized variables for space efficiency; uninitialized variables do not have to occupy any actual disk space in the object file.
Randal E. Bryant explains in his famous book on Computer Systems: A Programmer's Perspective, Why is uninitialized data called .bss?
The use of the term .bss to denote uninitialized data is universal. It was originally an acronym for the "Block Storage Start" instruction from the IBM 704 assembly language (circa 1957) and the acronym has stuck. A simple way to remember the difference between the .data and .bss sections is to think of "bss" as an abbreviation for "Better Save Space!"

Stack Segment

Stack segment is used to store all local variables and is used for passing arguments to the functions along with the return address of the instruction which is to be executed after the function call is over. Local variables have a scope to the block which they are defined in; they are created when control enters into the block. Local variables do not appear in data or bss segment. Also all recursive function calls are added to stack. Data is added or removed in a last-in-first-out manner to stack. When a new stack frame needs to be added (as a result of a newly called function), the stack grows downward (See the figure 1).


Code and Data Segments
Fig 1. - Memory layout of a C program

Heap Segment

Heap segment is also part of RAM where dynamically allocated variables are stored. In C language dynamic memory allocation is done by using malloc and calloc functions. When some more memory need to be allocated using malloc and calloc function, heap grows upward as shown in above diagram.
The stack and heap are traditionally located at opposite ends of the process's virtual address space.

Check Size of Code, Data, and .BSS Segments

The size command, a GNU utility, reports the sizes (in bytes) of the text, data, .bss segments, and total size for each of the object or archive files in its argument. By default, one line of output is generated for each object file or each module in an archive. The size command has no information for stack and heap sections because the size of those areas is decided on run-time.
For example, see the following C program and the size of its object file.

#include <stdio.h>
 
int main ()
{
  unsigned int x = 0x76543210;
  char *c = (char*) &x;
 
  if (*c == 0x10)
  {
    printf ("Underlying architecture is little endian. \n");
  }
  else
  {
     printf ("Underlying architecture is big endian. \n");
  }
 
  return 0;
}
For the above mentioned program check-endianness.c (which finds whether the underlying architecture is little endian or big endian) the size of text, data, .bss segments, and the total size is examined as follows with help of the size command. The fourth and fifth columns are the total of the three sizes, displayed in decimal and hexadecimal, respectively. You can read man page of size for more details.
[root@host ~/cprogs]$ gcc check-endianness.c -o check-endianness
[krishaku@adc6140630 ~/cprogs]$ size check-endianness
   text    data     bss     dec     hex filename
   1235     492      16    1743     6cf check-endianness

Last Word

In this tutorial we talked of memory layout of a C program, and its various segments (text or code segment, data, .bss segments, stack and heap segments). Hope you have enjoyed reading this article. Please do write us if you have any suggestion/comment or come across any error on this page. Thanks for reading!

Tuesday, 23 September 2014

How to formate Pen drive in opensuse?

Today I was wondering how to format pen drive in opensuse I searched some site

Mounting USB pen drive
1. In Ubuntu desktop, the USB pen drive will be detected and mounted automatically. In Ubuntu server command line terminal, a message will appear to notice you that some information about the USB pen drive that has been plug in or alternatively you can use fdisk command to check whether USB has been mounted or not. Here is sample

how to mount usb drive in ubuntu using terminal

1.a. If you get same output as mine then you can get mount location by using mount command

mount USB drive in Linux Mint

2. If Step 1 didn't work for you, then run dmesg command to identify the correct device name corresponding to the USB pen drive

$ dmesg

[19197.235469] sd 25:0:0:0: [sdb] Write Protect is off
[19197.235476] sd 25:0:0:0: [sdb] Mode Sense: 0b 00 00 08
[19197.236972] sd 25:0:0:0: [sdb] No Caching mode page present
[19197.236982] sd 25:0:0:0: [sdb] Assuming drive cache: write through
[19197.242047] sd 25:0:0:0: [sdb] No Caching mode page present
[19197.242055] sd 25:0:0:0: [sdb] Assuming drive cache: write through
[19197.279672] sdb: sdb1 --> Device name
[19197.282401] sd 25:0:0:0: [sdb] No Caching mode page present
[19197.282406] sd 25:0:0:0: [sdb] Assuming drive cache: write through
[19197.282410] sd 25:0:0:0: [sdb] Attached SCSI removable disk
[19199.953227] usb 2-1.1: USB disconnect, device number 28

2.a. Create Mount Point

$ mkdir -p /media/usb

2.b. Mount USB pen drive

$ sudo mount /dev/sdb1 /media/usb

Unmounting USB pen drive


1. To unmount a USB device simply run the following command

$ sudo umount /dev/sdb1

OR

$ sudo umount /media/usb

NOTE: /media/usb is a mount point.

Formatting USB pen drive


1. First make sure that USB device is not mounted, if it is then unmount it.

2. Format USB device in fat32 format

$ sudo mkfs.vfat /dev/sdb1

Note: You can use mkfs.ext3 to format to ext3 filesystem.

Caution: Enter your device name correctly otherwise it will wip out your entire data.

3. Format and change the Label of the USB drive.

$ sudo mkfs.vfat -n 'sandeep' /dev/sdb1




mount -o remount,rw /media/THE_ONE/
rm -R -f /media/THE_ONE/IMAG2781.jpg

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