Showing posts with label kernel. Show all posts
Showing posts with label kernel. Show all posts

Friday, September 19, 2014

Add a Custom System Call in Linux Kernel

Here I will be covering a small tutorial on creating new system call in Linux Kernel. I am using Latest Kernel version 3.16 ( It is latest at the time of blog written).
I added my call for 32 bit system only. 

So the whole process is divided in 5 step.

Step 1:  Open arch/x86/syscalls/syscall_32.tbl . Here go to the last line in the file. It will be containing a number in first column, this number tells that it is the last number used by system for system call. So lets say the number is 356, so your new system call will have number 357. Now just duplicate the last line, and change the number and name of the sys call. Let say it is "hello". So the whole line will look like :

357    i386    hello   sys_hello

Step 2: Add the syntax of syscall in  include/linux/syscalls.h. Suppose this sys call takes 2 int parameters. So for syscall "hello", your new line should be like this :

asmlinkage long sys_hello(int a, int b);

Step 3:  Now add the entry in /kernel/sys_ni.c. So entry will be like :

cond_syscall(sys_hello);

Step 4: Add the function definition for sys call. Open kernel/sys.c. you can add it at different place too.  Now as our sys call is having two parameters, so the function will look like this :

SYSCALL_DEFINE2(hello /*name of syscall */, int /*type of first parameter */,  a /*name of first parameter*/, int /*type of second parameter */,  a /*name of second parameter*/)
{
int error = -EINVAL;
// code for whatever you want to do in syscall 

return 0;
}

That's it, your system call is created, but to reflect it in your kernel, you have to build it. you can refer my blog 


Step 5:  Test the system call. create a userspace program. Don't forget to add sys/syscall.h header. 

Now to call our hello syscall. 

int call = syscall(357, 1,2); // here 357 is our system call number, 1 is val for a and 2 for b.


That will be all from my side. I hope it help you to understand syscall. 

Thursday, July 24, 2014

Short Notes on Memory in Linux

Most of part of this blog will be containing notes from Robert Love's Linux Kernel Development. But I will try to add the general questions also in this blog.


The most basic unit of memory is page. Kernel use page structure to keep track of all the pages in the system. Through this kernel can be informed that whether page is used or free, if used then who is using it etc.

Zone : Because of hardware limitation the kernel can't treat all pages identical. So it is divided in 3 parts mostly : ZONE_DMA(upto 16 MB), ZONE_NORMAL(16 to 896 MB) and ZONE_HIGHMEM(896 & above).

Main limitation to divide pages in Zone are:
1. Some hardware devices can perform DMA to only certain memory address.
2. Some memory can't be permanently mapped into kernel address space.(eg: HIGMEM)

Page allocation interface :

1. struct page * alloc_pages(gfp_t gfp_mask, unsigned int order) : This returns 2 to the power order pages contiguous physical page. As this function returns a page pointer, to get the logical address of it, we use page_address(struct page * page) method.
2. unsigned long  __get_free_pages(gft_t gfp_mask, unsigned int order) : it returns the logical address.
3. unsigned long get_zeroed_pages(gfp_mask) : it is useful for page allocated for user space, as it zeroes the content of allocated page, so that sensitive data doesn't pass to user space.
4. void * kmalloc(size_t size, gfp_t flags): this function returns a pointer to a region of memory that is atleast size bytes in length. This memory is physically contiguous.
5. vamlloc() : it allocates virtually contiguous memory. It does this by allocating potentially non contiguous chunks of physical memory and fixing the page table to map the memory into a contiguous chunk of virtual memory.

Deallocation interface :

1. __free_pages(struct page *page, unsigned int order) : Always ensure you are deallocating only those page which you allocate.
2. kfree(const void *ptr)
3. vfree(const void *ptr)

Introduction to Slab Layer:
Allocation and deallocation memory is the most common operation in Kernel. Because of it, there is good chance of de-fragmentation. Which is complete waste of resources, as you are having the free memory but you cant use it as it is not contiguous.
To resolve this issue, Linux kernel came up with the slab layer concept. So most frequently used data structure is allocated through cache. At the start-up we create the caches for all major data structure. Cache is further divided in slab. And slab contains a page. Apart from that Cache also maintain 3 list, empty list, full list and partial list.
So whenever allocation request comes, Cache check whether any empty page is there on any of the list. It allocates there and then return the page. Once that structure is released, the corresponding page is also released and return back to the free list.

This was the basics, now lets try with questions which I faced, these questions may not in order of relevance:

1. What is the return address of kmalloc() ? Physical or Virtual?
Ans : it always return the virtual address, and the allocated memory region will be physically as well as virtually contiguous.

2. How memory is allocated for program ?
Ans : When ever program compilation is done. At the time of loading, First program is loaded in memory, then mapped it to the Virtual memory. So it will be having page table with no association with physical memory. At the time of use, means when you want some memory for operation, it goes to page table, there MMU find that no physical memory is allocated, so it do the page_fault(). Then the physical memory is allocated and corresponding entry is created in the page table.

3. logical address and virtual address ?
Ans : Most important thing is logical address comes in picture if you have segmentation unit in your system. If it is not there then there is no logical address. So the address translation happens like this :
           logical address => [segmentation unit] => virtual address => [paging unit] => physical address

4. Why physically contiguous memory region is more efficient than virtually contiguous memory?
Ans : As memory allocated is physically contiguous can use a concept called huge pages. With this higher page size can be used, so correspondingly there will be lesser page entries in the table.Huge pages can improve performance through reduced page faults (a single fault brings in a large chunk of memory at once) and by reducing the cost of virtual to physical address translation (fewer levels of page tables must be traversed to get to the physical address). 

5. How Shared memory is used?
Ans : For shared memory we use IPC like shmem. So whenever two process wants to share some memory. They use shmem IPC to get an id for the associated memory, further this shared memory is mapped to both processes's address space. So for those process it looks like local memory. Internally the vm_area_struct (virtual memory area) uses VM_SHARED flag to show this memory area as shared memory.
           Also when we create a child process with CLONE_VM flag, at the time of creation it skips the allocate_mm() call (which is actually responsible for memory allocation) and assign it's mm structure to its parent's mm structure. 

6. Where does the memory is allocated for kernel stack ?
Ans : Kernel stack is allocated in the kernel space, remember not is user space memory. But it is mapped to that Process's address space, not only that but to all other process's address space. As apart from kernel no body will be using this, so it no process is able to recognize it and they don't have permission to access it.

7. Can a process use whole 4 GB address ?
Ans : No, it can't. Remember, memory is divided in memory area. So a process can only access only those memory areas for which it has permission. Even to add or remove memory area, it has to request kernel.




Wednesday, April 23, 2014

kmalloc() V/S other page allocation methods

If you are developing anthing in Kernel, I hope you have used kmalloc() many times till now. But if you see there are other function also to allocate physical memory. Those are :

__get_free_page(unsigned int gfp_mask)
__get_free_pages(unsinged int gfp_mask, int order)
get_zeroed_page(unsigned int gfp_mask)

So when we use kmalloc() and when we use the above functions ?
Answer lies in your requirement, if you need very small memory to allocate, go for kmalloc, because there you define the minimum no of bytes(let say n) you need to allocate. But remember it just ensure that atleast n bytes will be allocated, but in reality, it allocates more than it, sometimes even double of the size. So in short there is no fine granuality with kmalloc().

while get_free_page family is used when you want to allocate memory in terms of pages, as for kernel, page is the smallest memory unit. So you will pass the order x, and it will return you 2 power x pages. So here Kernel ensures that only requested no of pages will be allocated. So there will not be any memory waste.

And if you want to allocate memory from high memory, then there is a seperate function : [Although these function can be used for normal zones too]

alloc_pages(unsinged int gfp_mask, unsigned int order)
alloc_pages(unsinged int gfp_mask)


Friday, March 21, 2014

Mutex Vs Binary Semaphore

Most of the time people get confused with these two. So here I will try to explain the difference using this answer at Stack Overflow.

So Mutex is a lock which have the owner association, So it means whoever holds the mutex lock will only be able to unlock this mutex. So Mutex is used when you want to lock the resources.

While Binary Semaphore is used for signalling mechanism, It doesn't lock the resource. So any other thread can also unlock the semaphore held by your thread. In other words it signals your thread to do something.

Thursday, March 20, 2014

GDB : Debugger for simple c file

Hi,

It may be out of track article for kernel, but it could be good if you have single file.
So GDB is a debugger utility in linux for debugging C/ C++ program.

Step 1 : So first how you will enable your program to do so :
In your compilation command, use -g option, for example :
gcc -g program.c -o program

Step 2 : Now to run the utility, just type gdb on the shell. It will give you something like (gdb) shell

Step 3:  Load the file which you want to debug,
             (gdb) file filename.c

Step 4 : Put break points at lines
             (gdb) break filename.c : Line number
             Put break points at function
             (gdb) break func_name

Step 5 : type run. It will run till it reaches your first break point.

Step 6 : Now suppose you want to check the value of some variable use print
             (gdb) print x

Step 7 : If you want to just go to next break point, just type
             (gdb) continue

Step 8 : If you want to go step by step, use either next/step command.
             (gdb) next
                 or
             (gdb) step
             Only difference is, next will treat any sub-routine call as a single instruction.

Now apart from break point there is one more concept as Watch point, it works on variable instead of function or line number. It will stop code execution when the value of variable on which watchpoint is set, has been changed. Syntax is
(gdb) watch variable_name

There are other command also

1. backtrace - produces a stack trace of the function calls that lead to a seg fault (should remind you of Java exceptions)
2. where - same as backtrace; you can think of this version as working even when you’re still in the middle of the program
3. finish - runs until the current function is finished
4. delete - deletes a specified breakpoint
5. info breakpoints - shows information about all declared
breakpoints

Also we can use condition in breakpoints, for example you want to break only when i < 1,so do like this :
(gdb) break program.c : 7 if i < 1.

Tuesday, March 18, 2014

Build kernel from source code

If you are newbie to the kernel, It is a matter of time when you have to download kernel source and build it. Although working in Linux kernel domain for 2 years, I never did it earlier, so finally today I did it because of eudyptula-challenge.org.

So here are the steps, you should do to build your kernel. 

Step 1 : Download the source code from git.

Step 2 : Set up the config file. It is the file which tells at the time of booting what all configuration needed to be enabled. So easiest way to create config file sudo make localmodconfig

Step 3 : Further if you want to modify any change in config file, use sudo make menuconfig. Now change any configuration you want, you can select y/n/m.

Step 4 : Now its time to build your kernel, you can use either make or you can use make deb-pkg

Step 5 : To install the image, 
- If you used make earlier, then call make install.
- If you used make deb-pkg, then install the image first:
sudo dpkg -i linux-image-3.14.0-rc6-00145-ga4ecdf8_3.14.0-rc6-00145-ga4ecdf8-8_i386.deb
Then install the headers :sudo dpkg -i linux-headers-3.14.0-rc6-00145-ga4ecdf8_3.14.0-rc6-00145-ga4ecdf8-8_i386.deb

you can replace the version accordingly in above commands.

After reboot, you will be able to see the new linux kernel in your grub list.




ARM 3-Stage Pipeline

What is Pipeline?
Pipeline is used to improve the perforamnce of the overall system by allowing multiple instructions(which are in different stage) parallely. So first understand the 3 stages of pipeline :

Fetch--------> Decode -----------> Execute

As per their names, In Fetch, we fetch the instructions, in Decode we decode the instruction and finally execure in Execute stage.

So keeping these 3 stages in mind, Whenever instuction 1 is in Executing stage(as it started first), instruction 2 will be in Decoding stage and instruction 3 will be in Fetching stage.

So if you see this, then there will not be any improvement for a single instruction, as every instruction will be taking the same 3 cycles to execute. But the overall performance will be improved.

Problem with pipeline: 
As like all other good things in the world, pipeline also have it share of cons. Pipeline creates problem when there is a branch instruction, because whenever branch instruction is in executing stage, It has to go to some other instruction instead of the instruction which processor had taken in fetch/decode stage while branch instruction was in fetch/decoding stage. I know it may be confusing, so lets understand this with an example:

[As I dont know assembly language, instruction syntax can be different what you expect]
1. ADD R1,R2,R3 [Add R2, R3 and keep it in R1]
2. ADD R2,R3,R4
3. SUB R3, R4,R5
4. JMP X
5. ADD R2,R3,R4
6. SUB R3, R4,R5
7. X:
8. ADD R1,R2,R3


So you can see when instruction 4(JMP) will be in execution stage, instruction 5 will be in decode stage and instruction 6 in fetch stage. But as isntruction 4 is a jump statement, thee is no use of executing instruction 5 and 6.
           In that case pipeline will be flush, and next 2 cycle will be waste. As for instruction 7 to execute, you will need 2 cycle, and as there is no eligible instruction to execute in pipeline, there will not be any output during this cycle.

So it is not necessary that pipeline will always improve performance.

Branch Prediction:
To overcome this problem caused by pipeline, Architecture came up with branch prediction. It tries to predict which could be executed next, . There are different ways to achieve this, I am not covering those here. you can refer wikipedia or ARM information center.

Sunday, March 16, 2014

Cache Management in ARM

What is Cache?
Cache is a place where a processor can put data and instruction. 

Why we need Cache?
As we know accessing memory to fetch instructions and data is way slower than processor clock, so fetching any instruction from the memory can take multiple clock cycle. To improve this scenario, ARM provides the concept of Cache, it is a small, fast block of memory which sits between processor core and memory. It holds copies of items in main memory. That way we have kept one intermediate small memory which is faster than main memory.

How it works?
If we have cache in our system, there must be a cahce controller. Cache controller is a hardware which manages cache without the knowledge of programmer. So whenever processor wants to read or write anything, first it will check it in the cache, this is called cache lookup. If it is there it will return the result to processor. If required instruction/data is not there, it is  known as cache miss. And request will be forwarded to main memory.
                            Apart from checking whether data/instruction existence in the cache, there is one more thing in core, which is a write buffer. Write buffer is used to save further time for processor. So suppose processor wants to execute a store instruction, what it can do is, it can put the relevant information such as which location to write, which buffer needs to copy, and what is the size of buffer which is getting copied into this write buffer, after that processor is free to do take next instruction, Write buffer will then put this data into the memory.

Level of Cache:
There are generally two caches(L1 and L2), some architecture have only one cahce(L1) too.
L1 caches are typically connected directly to the core logic that fetches instructions and handles load and store instructions. These are Harvard caches, that is, there are separate caches for instructions and for data that effectively appear as part of the core. Generally these have very small size 16KB or 32KB. This size depends on the capability of providing single cycle access at a core speed of 1GHz or
more.
             Other is L2 cache, these are larger in size, but slower and unified in nature. Unified because it uses single cahce for instructions and data. L2 cache could be part of core or be a external block.

Cache Coherency:
As every core has its own L1 cache, It needs a mechanism to maintain the coherency between all the caches, because if one cache is updated and other is not, This will create data inconsistency.
There are 2 ways to solve this scenario:

1. Hardware manage coherency : It is the most efficient solution. So the data which is shared among caches will always be updated. Everything in that sharing domain will always contain the same exact value for that share data.
2. Software manager coherency : Here the software, usually device drivers, must clean or flush dirty data from caches, and invalidate old data to enable sharing with other processors or masters in the system. This takes processor cycles, bus bandwidth, and power.

Wednesday, March 12, 2014

why to use request_threaded_irq?

I know for many this function may be very clear, but I found it really difficult to digest this function. So lets start it :

Why we need it ?
From the starting, it was desired for kernel to reduce the time for which processor stays in interrupt context. To solve this initially they introduced Top half and bottom half concept, in which they keep time critical task in top half and rest of the work they kept in bottom half. When processor is executing the interrupt handler it is in interrupt context with interrupts disabled on that line, which is not good because if it is a shared line, other interrupts won't be handled during this time, which in turn effect the overall system latency.
               To overcome this problem, kernel developers came up with the request_threaded_irq() method which futher reduces the time.

How it works?
Before going further with the functionality, lets check the function definition first

int request_threaded_irq (unsigned int irq,
 irq_handler_t handler,
 irq_handler_t thread_fn,
 unsigned long irqflags,
 const char * devname,
 void * dev_id);



Difference between this function and usual request_irq function is the extra thread_fn. 
Now lets understand the functionality, request_threaded_irq() breaks handler code in two parts, 1st handler and 2nd thread function. Now main functionality of handler is to intimate Hardware that it has received the interrupt and wake up thread function. As soon as handler finishes, processor is in process context. 
so processor is free to receive new interrupts. It improves the overall latency.

Misc:
Some driver code uses request_threaded_irq() with NULL as a value for handler, in that scenario kernel will invoke the default handler, which simply wakeup the thread function.

When to use request_threaded_irq instead of bottom halves ?
Answer lies in the driver's requirement, if it wants to sleep put the code in thread fn and user threaded function. 

Thursday, March 6, 2014

DMA : Direct Memory Access

Why we use it ?
In normal scenario whenever data transfer is done, processor should be informed. If there is more data, it could lead a lot of time of CPU.  To overcome this issue, DMA concept came in picture, using DMA, computer can access system memory without telling Processor. 
Earlier when DMA was not there, CPU will be busy when transfer is happening, but now with DMA, CPU can do other operations while transfer is happening.

Misc:
DMA has its configuration, which describe what it will be transfering, from where it will be taking data. what is the size? There are many other settings too. There will be one internal buffer also, which will be taking data from source and then putting it at destination.

When we want to start the transfer, there will be one bit associated, when you write it, it will intiate the transfer.

 

Thursday, February 27, 2014

I2C Communicatiom

I2C (Inter-Integrated Circuit) protocol is used to transfer data between Master and Slave device. There are 2 lines between master and slave, one for data and other for clock. 

I2C is synchronous transfer mechanism, as it uses clock to control the data. So for a particular transfer, Master/ Slave will be transferring/recieving at the same rate. 

Master is known as master, because only it is who can initiate the transfer.

There are two type in which you can register a slave device, either it is connected to interrupt controller, or through GPIO lines you can use it. When registering to interrupt controller we use "i2c" while in other case we use it as "i2c-gpio". 

In device side, we define i2c_board_info for every slave, this will containg slave name, slave address, also platform data. Futher this slave will be register using i2c_register_board_info(), in this method we will pass the bus number and the slave.

Flow will differ if we are using gpio, there we will create device as name "i2c-gpio" and bus number, it will pass this device in platform_add_devices() to get it registered.


At driver side, we will be define all functions like probe, remove, NAME(it should be same), pm_ops. Finally we will call i2c_add_driver(). So as soon as linking between device and driver happens, it will call probe function. 

Now lets take example of Touch, there whenever user touches screen, it will generate the interrupt(it was registered in probe). Through this only Master(touch screen driver) will know that there is some data available at the slave side which needs to be read. Then it will initiate the connection and read data one by one. same is applicale for reading, a little bit flow changes for it.



Tuesday, February 18, 2014

Memory Management in Linux

This post is going to be little vague. As I will not be explaining all the basics which most of the book of the same topic covers.

Lets talk about kernel memory allocation Most of the time we use kmalloc() function. Although it is supposed to be used only when kernel need contiguous physical memory. But to save overhead caused by vmalloc(), most of the time kmalloc() is preffered.

So How it allocates ?
Before that first we should understand the hierarchy, on top kmalloc() call is there, then slab allocator comes and finally buddy allocator which finally interacts with the physical memory. So at the time of boot up, slab allocator asks buddy allocator to return a fixed no of pages. Further slab allocator will divide those pages in different size of Caches(like 32, 64 ...MAX byte).
Now suppose in your kernel code you want to allocate a memory for int using kmalloc(), it will search the position for this data only in 32 bit slab. Further every slab has 3 lists, full, partial and empty. These list will have pages. So whenever it wants to allocate a memory for any object, it will first check if any partial page available for that slab, if yes it will allocate memory in that page, if not it will check for free pages, if there also no page is available it will ask buddy allocator to give new page.

Use of High Memory:
It is used when you have more physical memory than required virtual memory. For example, for 4GB virtual memory and 1.5 GB RAM, you will have 1 GB for kernel and 3GB for user space. So you have more physical memory (1.5 GB) than virtual memory(1 GB).
So there is no one to one mapping exists between physical and virtual memory, to solve this problem, in x86 architecture, they created one-to-one mapping for upto 896 MB, memory more than that will be dynamically mapped, so for high memory page will have NULL as a virtual address in page structure.

Tuesday, February 11, 2014

Semaphore

As we discussed in previous post, Spinlock is spinning lock, the same way Semaphore is sleeping lock.
So think of a scenario in which a task want to acquire a semaphore which is not available, so it will go to sleep  and semaphore will put it on a wait queue. Once this semaphore becomes available, scheduler will invoke any of the task on this waitqueue.

Properties:
1. As the task holding semaphore can sleep, it is best suitable for the task which runs for longer duration.
2. As the task holding semaphore can sleep, it can only be used in Process Context.
3. Task cant hold a spinlock if it wants to acquire a semaphore. Because task might want to sleep while waiting for semaphore, but this will cause processor to sleep for infinte time(if it is holding spinlock), as there is no one to wake it up. 

Monday, February 10, 2014

Spin lock

Lets start with spin lock. First we will understand what is it and further I will try to cover few doubts about it, which could be quite useful in Interviews.

What is Spin lock :
Spin lock is a lock that can be held by at most one thread of execution. Suppose one thread is trying to acquire a spin lock, so first it will check whether this spinlock is held by other thread or not, if it is available it will acquire the lock otherwise it will constantly keep on checking (busy looping) for this lock.

Properties :
1. It should be held for small duration only, because during the time a spin lock is held no other thread can be scheduled on that processor.
2. On uni processor, if spin lock is held, it means it will now behave as kernel preemption is disable. As no other thread can run.
3. On Multi processor, no other thread will be able to take this spin lock.
4. If interrupt handler needs to use lock, they can use spinlock. Also we must ensure that local interrupts are disable before obtaining the lock. Otherwise, it is possible for an interrupt handler to interrupt the kernel code while lock is held. This in turn will make interrupt handler to spins, waiting for the lock to become available while lock holder thread will wait interrupt handler to complete. This is deadlock.

Now another scenario, Suppose you disabled interrupt on local processor and a process is holding the lock. At the same time interrupt came on other processor, it will make process to release the spinlock.


Wednesday, February 5, 2014

Why Interrupts can't sleep ? And Nested Interrupt

So Lets start with a simple and very important question, why Interrupt can't sleep.

First go back to our understanding to User Context, there we can sleep why? because when you sleep in it, you can call schedule() which can ask other processes to run.

But when you are in Interrupt context, the only thing residing on that Processor is the Interrupt handler(of the respective interrupt). So if you sleep now, there is nothing else to schedule. So its like processor itself is in sleep which is not good at all.

Nested Interrupt

Now there are few things associated with Interrupt, like nested interrupts. So Nested interrupt is when you are running and interrupt handler and more interrupts come on the same line. So in interrupt handler you are getting another interrupt.

When this situation arises ?
Suppose for some reason you need to call enable_irq() in interrupt handler, so it means you are telling your hardware that you are ready to receive the new interrupt.

How Kernel Handles it ?
For this situation, Kernel have third mode called System Mode( apart from user and kernel mode). This is also a privileged mode. So if you want to enable nested interrupt you should change mode to system, and then you should enable interrupt. Before enabling interrupt, you keep LR and SPSR of IRQ mode in Stack of System mode.
This way we save LR and SPSR from being corrupted. And once the new interrupt handled it can return to the previous interrupt and finally it can go back to original location.
you can refer this link for more clarity. 

Wednesday, June 19, 2013

How To Enable debugfs in kernel dynamically.

Kernel developer has provided a functionality known as “debugfs” to debug the kernel, enabling the log at the run time. It is very useful for the modules which have a lots of logs, and enabling the log statically will make the system very slow. So Kernel developers came up with this idea to enabling the logs only for the time when user wants to check a particular scenario.
So here is the process to enable it :
Step 1. Enable the debugfs, which can be done by following command :
mount -o rw,remount -t debugfs none /sys/kernel/debug
Step 2. Now if you want to see what are the logs defined you can do the same using following command :
cat /sys/kernel/debug/dynamic_debug/control [Here /sys/kernel/debug/ is the directory we mounted in previous command,                    u can change it if you want]
Step 3. Now enable the debug log for the files or paricular function you want to see in the logs:
echo ‘file mdp.c +p’ > /sys/kernel/debug/dynamic_debug/control [It will enable all debugfs logs in mdp.c]
echo ’file mdp.c line 2921 +p’ > /sys/kernel/debug/dynamic_debug/control [It will only enabled the log at 2921 line in mdp.c file]
# (
> echo ’file svcsock.c line 1603 +p’ ;\
> echo ’file svcsock.c line 1563 +p’ ;\
> ) > /sys/kernel/debug/dynamic_debug/control [for enabling to multiple debug logs]
Step 4. Now you can check the logs in demsg or cat /proc/kmsg.
Here I want to mention the logs which used under pr_debug()/dev_dbg() method will be enabled by this feature.So whatever logs you want to enable put those using pr_debug or dev_dbg().
you can find more details for pattern to enable logs @ https://www.kernel.org/doc/ols/2009/ols2009-pages-39-46.pdf

Relation between device registration and driver registration

Hi all,
Today I observe one interesting thing during calling platform_driver_register(). The normal thing is if you have a device, and also a driver, It will be linked. But suppose you want to do some different functionality with the device, like you want to do some initialization of few variables  before starting the real functionality of the device.  So a nice way to do this is create multiple device with the same name but different id and register those usingplatform_device_register() or platform_add_devices().
So now when you will call platform_driver_register(), it will check for all devices available with the same name and the same number of probe() function will be called. Here in probe function you can put your logic for initialization according to your id.
Hope it will help you.

Tuesday, March 6, 2012

When to use the workqueue in driver code / What is workqueue

Hey guys,
Here is one more post about kernel, As I am going through Kernel code, I feel this doubt. Theoretically it is assumed that workqueue increased the performance. As you are allowing the interrupt to be enabled. So it means you are ready to handle another interrupt while putting the previous interrupt handler code in workqueue.
But is it a good way to put all the interrupt handler code in the workqueue function, The Answer is NO. Why ? To be part of my belief first you have to understand the basic functionality of workqueue. Linux Kernel developer came with this concept, because they want to reduce the overhead of unnecessary execution of code at the cost of performance(As no other interrupt will be allowed during that time). So what they do is, they divided the functionality in two parts, crucial part and the normal part. With this approach they decided which code should be executed before enabling the interrupt and which part should be executed later.
In summary,what developer should do is, decide the importance of the code in terms of functionality and performance and accordingly put the rest of the Not-so-Crucial part in the work function.
Hope it will help.

Thursday, March 1, 2012

Difference between schedule_work() and queue_work()

Hi Guys,
If you are newbie in Linus Kernel, you may have this doubt that what is the difference between these two methods,basically it is related to the choice that whether you want a dedicated workqueue(which in turn will need dedicated kernel thread) for your driver or you just want to use the default workqueue provided by kernel.
So if you want to control the workfunction in terms of scheduling independently,
you should go for create_workqueue method to create a workqueue. This function will create a workqueue and which in turn will create a seperate Kernel Thread on each and every processor available. Here I would also like to introduce a different version of same method which iscreate_singlethread_workqueue(), you should use this function only when you want to create only a single thread for all the processor.

Monday, January 23, 2012