Creation of proc entrt using proc_create_data in kernel version 3.10 and above.

In the post “Creating read only proc entry in kernel versions above 3.10. ” we saw how to create a proc entry using the function proc_create.

Note: The following module is valid only of kernel version 3.10 and above.

Another function available in kernel version 3.10 and above for creation of proc entry is proc_create_data which is defined in proc_fs.hs as

struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,struct proc_dir_entry *parent,const struct file_operations *proc_fops,void *data);

Where

name: The name of the proc entry
mode: The access mode for proc entry
parent: The name of the parent directory under /proc
proc_fops: The structure in which the file operations for the proc entry will be created.
data: If any data needs to be passed to the proc entry.

For example to create a proc entry by the name “hello” under /proc the above functions will be defined are

proc=proc_create_data(“hello”,0,NULL,&proc_fops,msg);

Along with creation of the entry we are also passing a function to the proc entry in using the porinter “msg”.

Now we need to create file_operations structure proc_fops in which we can map the read function for the proc entry.

struct file_operations proc_fops = { read: read_proc };

Next we need to add the function read_proc which will give to the user space the data that we want to export from the kernel space.

int read_proc(struct file *filp,char *buf,size_t count,loff_t *offp ) { char *data; data=PDE_DATA(file_inode(filp)); if(!(data)){ printk(KERN_INFO “Null data”); return 0; } if(count>temp) { count=temp; } temp=temp-count; copy_to_user(buf,data, count); if(count==0) temp=len; return count; }

To access the data in the proc_dir_structure we need to make use of the function PDE_DATA to which we pass the file pointer. The function in turn returs a pointer to the data that was passed during the creation of the proc entry.

The message that we want to display will be defined in the function create_new_proc_entry in which we will also call the fuction for creation of proc entry.

void create_new_proc_entry() { msg=”Hello World “; proc=proc_create_data(“hello”,0,NULL,&proc_fops,msg); len=strlen(msg); temp=len; }

The init and clean up functions for the module are

int proc_init (void) { create_new_proc_entry(); return 0; } void proc_cleanup(void) { remove_proc_entry(“hello”,NULL); }

The full code for creation of proc entry using proc_create_data is

proc_read_data.c

#include #include #include #include #include #include #include #include struct proc_dir_entry *proc; int len,temp; char *msg; int read_proc(struct file *filp,char *buf,size_t count,loff_t *offp ) { char *data; data=PDE_DATA(file_inode(filp)); if(!(data)){ printk(KERN_INFO “Null data”); return 0; } if(count>temp) { count=temp; } temp=temp-count; copy_to_user(buf,data, count); if(count==0) temp=len; return count; } struct file_operations proc_fops = { read: read_proc }; void create_new_proc_entry() { msg=”Hello World “; proc=proc_create_data(“hello”,0,NULL,&proc_fops,msg); len=strlen(msg); temp=len; } int proc_init (void) { create_new_proc_entry(); return 0; } void proc_cleanup(void) { remove_proc_entry(“hello”,NULL); } MODULE_LICENSE(“GPL”); module_init(proc_init); module_exit(proc_cleanup);

The makefile for the compilation of the modules are

ifneq ($(KERNELRELEASE),) obj-m := proc_read_data_3_10.o else #KERNELDIR ?= /lib/modules/$(shell uname -r)/build KERNELDIR ?= /home/nitin/Desktop/src/linux-3.11.1/ PWD := $(shell pwd) default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules endif clean: $(MAKE) -C $(KERNELDIR) M=$(PWD) clean

Compile and load the module using

$ make $ sudo insmod proc_read_3_10.ko

We can see the output by using the cat command $ cat /proc/hello Hello World

Related Posts:

Creating read only proc entry in kernel versions above 3.10.

For kernel version before 3.10

Creating a proc entry – 1

Creating a proc read entry

Category: Linux | Comments Off on Creation of proc entrt using proc_create_data in kernel version 3.10 and above.

Creating read only proc entry in kernel versions above 3.10.

The creation of proc entries has undergone a considerable change in kernel version 3.10 and above. In this post we will see one of the methods we can use in linux kernel version 3.10 and above let us see how we can create proc entries in version 3.10 and above.

The function is defined in proc_fs.h as

static inline struct proc_dir_entry *proc_create(const char *name, umode_t mode,struct proc_dir_entry *parent, const struct file_operations *proc_fops)

Where:

name: The name of the proc entry
mode: The access mode for proc entry
parent: The name of the parent directory under /proc
proc_fops: The structure in which the file operations for the proc entry will be created.

For example to create a proc entry by the name “hello” under /proc the above function will be defined are

proc_create(“hello”,0,NULL,&proc_fops);

Now we need to create file_operations structure proc_fops in which we can map the read function for the proc entry.

struct file_operations proc_fops = { read: read_proc };

Next we need to add the function read_proc which will give to the user space the data that we want to export from the kernel space.

int read_proc(struct file *filp,char *buf,size_t count,loff_t *offp ) { if(count>temp) { count=temp; } temp=temp-count; copy_to_user(buf,msg, count); if(count==0) temp=len; return count; }

The message that we want to display will be defined in the function create_new_proc_entry in which we will also call the fuction for creation of proc entry.

void create_new_proc_entry() { proc_create(“hello”,0,NULL,&proc_fops); msg=” Hello World “; len=strlen(msg); temp=len; printk(KERN_INFO “1.len=%d”,len); }

The init and clean up functions for the module are

int proc_init (void) { create_new_proc_entry(); return 0; } void proc_cleanup(void) { remove_proc_entry(“hello”,NULL); }

The full code of module for creation of proc entry using proc_create is

#include #include #include #include#include int len,temp; char *msg; int read_proc(struct file *filp,char *buf,size_t count,loff_t *offp ) { if(count>temp) { count=temp; } temp=temp-count; copy_to_user(buf,msg, count); if(count==0) temp=len; return count; } struct file_operations proc_fops = { read: read_proc }; void create_new_proc_entry() { proc_create(“hello”,0,NULL,&proc_fops); msg=” Hello World “; len=strlen(msg); temp=len; printk(KERN_INFO “1.len=%d”,len); } int proc_init (void) { create_new_proc_entry(); return 0; } void proc_cleanup(void) { remove_proc_entry(“hello”,NULL); } MODULE_LICENSE(“GPL”); module_init(proc_init); module_exit(proc_cleanup);

The makefile for the compilation of the module is

ifneq ($(KERNELRELEASE),) obj-m := proc_read_3_10.o else #KERNELDIR ?= /lib/modules/$(shell uname -r)/build KERNELDIR ?= /home/nitin/Desktop/src/linux-3.11.1/ PWD := $(shell pwd) default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules endif clean: $(MAKE) -C $(KERNELDIR) M=$(PWD) clean

Compile and load the module using

$ make $ sudo insmod proc_read_3_10.ko

We can see the output by using the cat command $ cat /proc/hello Hello World

We can see that the message that we passed in the read function of the module is being displayed when the proc entry is read.

Related Posts : For kernel version before 3.10 Creating a proc entry – 1 Creating a proc read entry

Category: Linux | Comments Off on Creating read only proc entry in kernel versions above 3.10.

Using Spinlock in linux : Example

In the post we see the various functions available for spinlock in Linux. Let us look at an example and see how it can be used in Linux.

In the following example we create two threads, thread1 and thread2. We initialize a spinlock “my_lock” and both the threads try to acquire the lock .

Thread1 is made to get to the lock first. After acquiring the lock thread1 waits for one minute before releasing the lock.

During this time thread2 attempts to acquire the lock too. We have used the function spin_trylock, so if the thread2 is unable to hold the spinlock it will return immediately with a return value of non zero.

Thus we will define a spinlock using

static spinlock_t my_lock=SPIN_LOCK_UNLOCKED

Starting with the spinlock in unlocked state.

We will create the two threads thread_fn1 and thread_fn2 using the function kthread_create.

The first thread function thread_fn1 will hold the lock and loop for approximately on minute the code for which is

int thread_fn1() { unsigned long j0,j1; int delay = 60*HZ; j0 = jiffies; j1 = j0 + delay; spin_lock(&my_lock); while (time_before(jiffies, j1)) schedule(); printk(KERN_INFO “In thread1”); spin_unlock(&my_lock); return 0; }

The second thread function thread_fn2 will try to hold try to hold the lock using spin_trylock.A sleep of 100ms is added at the beginning to make sure that the first thread gets to the lock first.Thus the code for the second thread function will be

int thread_fn2() { int ret=0; msleep(100); ret=spin_trylock(&my_lock); if(!ret) { printk(KERN_INFO “Unable to hold lock”); return 0; } else { printk(KERN_INFO “Lock acquired”); spin_unlock(&my_lock); return 0; } }

If the thread_fn2 is able to get the lock we will see the message “Lock acquired” in the kernel log. If the thread_fn2 is unable to get the lock we will see the message “Unable to hold lock” in the kernel log.

The complete code will be

spinlock_example.c

#include #include #include #include // for threads #include // for task_struct #include #include static struct task_struct *thread1,*thread2; static spinlock_t my_lock = SPIN_LOCK_UNLOCKED; int thread_fn1() { unsigned long j0,j1; int delay = 60*HZ; j0 = jiffies; j1 = j0 + delay; spin_lock(&my_lock); while (time_before(jiffies, j1)) schedule(); spin_unlock(&my_lock); return 0; } int thread_fn2() { int ret=0; msleep(100); ret=spin_trylock(&my_lock); if(!ret) { printk(KERN_INFO “Unable to hold lock”); return 0; } else { printk(KERN_INFO “Lock acquired”); spin_unlock(&my_lock); return 0; } } int thread_init (void) { char name[8]=”thread1″; char name1[8]=”thread2″; thread1 = kthread_create(thread_fn1,NULL,name); if((thread1)) { wake_up_process(thread1); } thread2 = kthread_create(thread_fn2,NULL,name1); if((thread2)) { wake_up_process(thread2); } return 0; } void thread_cleanup(void) { int ret,ret1; ret = kthread_stop(thread1); if(!ret) printk(KERN_INFO “Thread stopped”); } MODULE_LICENSE(“GPL”); module_init(thread_init); module_exit(thread_cleanup);

Save the file as spinlock_example.c

Makefile required for compilation.

ifneq ($(KERNELRELEASE),) obj-m := spinlock_example.o else KERNELDIR ?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules endif clean: $(MAKE) -C $(KERNELDIR) M=$(PWD) clean

Compile and load the file

$ make $ insmod spinlock_example.ko

To check if second thread was able to get the lock run the command dmesg

$ dmesg Unable to hold lock

Thus we can see that the spin_trylock faile to acquire the lock and returned the error message. Instead of spin_trylock if we use spin_lock, the second thread will wait on the lock as long as the thread does not become available.

Note: Do not try changing the code from spin_trylock to spin_lock if you have a uniprocessor system. It might freeze your system and force you to do hard reboot.

Category: Linux | Comments Off on Using Spinlock in linux : Example

Spinlocks in linux

We saw in the post “Introduction to spinlocks” how spinlock can be used to achieve mutual exclusion.

Let us further look at the practical implementation of spinlocks in Linux.

Spinlocks are declared in Linux using the datatype “spinlock_t”. The spin lock variable can one of the two values

SPIN_LOCK_UNLOCKED SPIN_LOCK_LOCKED

We can initialize the value of the spinlock to either of the values by just eqating it to the value, i.e.

static spinlock_t lock=SPIN_LOCK_UNLOCKED

Thus the lock starts in an unlocked state. We can also assign the value to the spinlock at runtime by using the function spin_lock_init

void spin_lock_init(spinlock *lock)

After the initialization we can use the spin lock any where in the code. To lock the spinlock before entering the critical section we can use one of the following functions

Locking:

Locking of a spinlock is nothing but changing the value of the spinlock variable from SPIN_LOCK_UNLOCKED to SPIN_LOCK_LOCKED.

The functions available to acquire the lock are as follows.

spin_lock :

void spin_lock(spinlock_t *lock)

Locks the spinlock if it is not already locked. If unable to obtain the lock, it will keep spinning on the lock until the lock becomes free.

spin_trylock:

int spin_trylock(spinlock_t *lock)

Locks the spinlock if it is not already locked. If unable to obtain the lock it exits with an error and does not spin lock.

spin_lock_irq :

spin_lock_irq(spinlock_t *lock)

Locks the spinlock if it is not already locked and also disables the interrupts after locking. If lock is not available it continues to spin on the lock until it becomes available

spin_lock_irqsave :

spin_lock_irqsave(lock, flags) :

Locks the spinlock if it is not already locked and also disables the interrupts, storing the state of the interrupts in the variable flags which is an unsigned long datatype, after locking. If lock is not available it continues to spin on the lock until it becomes available.

Before exiting the critical section any process that locks the spinlock has to unlock the spinlock. For every lock function that we saw above there are corresponding unlock functions as listed below.

Unlock:

Unlocking a spinlock is nothing but changing the value of the lock variable from SPIN_LOCK_LOCKED to SPIN_LOCK_UNLOCKED.

The functions available for unlocking a spinlock are as follows

spin_unlock:

void spin_unlock(spinlock_t *lock)

Unlock the spinlock, changing the value of the spinlock variable from SPIN_LOCK_UNLOCKED to SPIN_LOCKED.

spin_unlock_bh:

spin_unlock_irq:

void spin_unlock_irq(spinlock_t *lock)

If the spinlock was locked using spin_lock_irq then the interrupts would have been disabled. Using this unlock function makes sure that the spinlock is unlocked as well as the interrupts are enabled.

spin_unlock_irqrestore:

void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)

If the spinlock was locked using the function spin_lock_irqsave, then the state of the interrupts which was stored also needs to be restored. Thus this function not only unlocks the function but also restores the state of interrupts to the same state as they were before they were disabled which was saved in the variable flags.

Category: Linux | Comments Off on Spinlocks in linux

Introduction to spinlocks

Spinlocks are one of the ways of achieving mutual exclusion that is, preventing multiple processes from entering the critical section simultaneously.
A spinlock has only two possible states, LOCKED and UNLOCKED.

A critical section can be surrounded by spinlock as shown below.

Critical section

Let us say two processes, A and B, want to execute the critical section and both reach the step of locking the spinlock at the same time.

Let us say process A is able to get a lock on the spinlock before process B. The process A can enter the critical section.
The process B will try to lock the spinlock but will fail as process A would have already locked it. As a result the process B will go into into an infinite spin on the lock, that is, it will keep checking for the availability of the lock repeatedly until the spinlock gets unlocked by process A. Because of this behavior of continuously spinning on the lock until it becomes available these are called as spinlocks

After finishing the execution of critical section process A will unlock the spinlock at which time the process B will be able to get the lock and enter the critical section.

Thus if a critical section is surrounded by a spinlock only one process can enter the critical section at any given time. Any number of processes can be spinning on the lock but only of the processes will be allowed to enter the critical section once the lock becomes available.

The following animation shows the working of a spinlock as explained above.

Spinlock animation

 photo spin_lock1.gif

Category: Linux | Comments Off on Introduction to spinlocks

modified scull code for 3.x.x

The scull code is the examples that the book, linux device drivers by Jonathan Corbet uses to explain the various concepts of character devices.

Here is the same code modified for 3.x.x kernel versions. The code has been tested in kernel version 3.7.5

main.c
access.c
pipe.c

Change the following line in scull.h

int scull_ioctl(struct inode *inode struct file *filp,unsigned int cmd, unsigned long arg); to long scull_ioctl(struct file *filp,unsigned int cmd, unsigned long arg);

Category: Linux | Comments Off on modified scull code for 3.x.x

Implementing an ioctl call (for kernel versions above 2.6.39)

In the post “Creating an ioctl command in linux ” we saw the basics of ioctl, and how we can create our own ioctl commands. The functions used to create ioctls have undergone a change from the kernel version 2.6.39,and the previous functions are no longer valid.

Before 2.6.39, the ioctl calls would lock the BKL (Big kernel lock) and then execute the required functions. This was unnecessary with the new fine grained locking available in the kernel. Thus to improve the implementation of ioctl, a new operation called unlocked_ioctl was introduced and all the existing ioctls were migrated to this new implementation.

Thus stating 2.6.39 the older implementation is no longer available.

The changes required in implementation of the ioctl are.

The function in the driver has changed from

int ioctl_funcs(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg)

long ioctl(struct file *filp,unsigned int cmd, unsigned long arg)

The inode is no longer passed as an argument.
The fops uses the name unlocked_ioctl

struct file_operations fops = { open: open, unlocked_ioctl: ioctl_funcs, release: release };

The basic working of ioctl remains same.
Here is a code that implements the above mentioned changes if the kernel version is more than 2.6.39, else uses the older interface.

Module: ioctl_basic.c

#include #include #include // required for various structures related to files liked fops. #include #include #include “ioctl_basic.h” #include static int Major; #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36) #define UNLOCKED 1 #endif int open(struct inode *inode, struct file *filp) { printk(KERN_INFO “Inside open \n”); return 0; } int release(struct inode *inode, struct file *filp) { printk (KERN_INFO “Inside close \n”); return 0; } #ifdef UNLOCKED long ioctl_funcs(struct file *filp,unsigned int cmd, unsigned long arg) { int ret=0; switch(cmd) { case IOCTL_HELLO: printk(KERN_INFO “Hello ioctl world”); break; } return ret; } struct file_operations fops = { open: open, unlocked_ioctl: ioctl_funcs, release: release }; #else int ioctl_funcs(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { int data=10,ret; switch(cmd) { case IOCTL_HELLO: printk(KERN_INFO “Hello ioctl world”); break; } return ret; } struct file_operations fops = { open: open, ioctl: ioctl_funcs, release: release }; #endif struct cdev *kernel_cdev; int char_arr_init (void) { int ret; dev_t dev_no,dev; kernel_cdev = cdev_alloc(); kernel_cdev->ops = &fops; kernel_cdev->owner = THIS_MODULE; printk (” Inside init module\n”); ret = alloc_chrdev_region( &dev_no , 0, 1,”char_arr_dev”); if (ret < 0) { printk("Major number allocation is failed\n"); return ret; } Major = MAJOR(dev_no); dev = MKDEV(Major,0); printk (" The major number for your device is %d\n", Major); ret = cdev_add( kernel_cdev,dev,1); if(ret < 0 ) { printk(KERN_INFO "Unable to allocate cdev"); return ret; } return 0; } void char_arr_cleanup(void) { printk(KERN_INFO " Inside cleanup_module\n"); cdev_del(kernel_cdev); unregister_chrdev_region(Major, 1); } MODULE_LICENSE("GPL"); module_init(char_arr_init); module_exit(char_arr_cleanup); The steps of compiling and testing the module are same as shown in the post “Creating an ioctl command in linux ”

Category: Linux | Comments Off on Implementing an ioctl call (for kernel versions above 2.6.39)

Pointer to structure from its member pointer: container_of

In c programming, we use structures to store variables of different data types in one kind of variable. Each variable in the structure is termed as a member of the structure. The memory allocation for these members is always sequential.
Example

struct temp { int i; char ch; }

In the above structure the addresses allocated for members “i” and “ch” will be sequential in the memory.

Using this property of the structure, if we know the pointer to a member of the structure we can retrieve the pointer to the structure with the help offsetof function.
In the post “offset of” we saw how we can retrieve the offset of a member with in the structure.

As the size occupied by each data type is fixed once we know the offset of the member and its pointer, we can subtract the offset from the pointer to get a pointer to the structure.

For example in the above structure if the pointer to the “char ch” is 1000. The offset of function will return 4 for “ch” as it is after an integer in the structure.
Thus the pointer to the structure would be “1000-4 = 996”.

The same is shown in the example code below.

We allocate memory for one structure,test1, of type “temp” and assign values to “i” and “ch”.

test1 = malloc(sizeof(struct temp)); test1->i = 10; test1->ch=”h”;

Then we assign the pointer of ch to a char pointer. ptr = &(test1->ch);

Then we subtract the offset of “ch” from the pointer and assign the return value to a new pointer to a structure,test2, of type temp.

test2 = (struct temp *) (ptr – offsetof(struct temp,ch));

If the pointer assigned to test2 is the correct , we should be able to access the value of “i” using test2.
Thus we print the value of “i” using test2

printf(“%d”,test2->i);

Here is the full code

struct_ptr.c

#include#include #includestruct temp { int i; char ch; } ; main() { int size; char *ptr; struct temp *test1; struct temp *test2; test1 = malloc(sizeof(struct temp)); test1->i = 10; test1->ch=”h”; ptr = &(test1->ch); test2 = (struct temp *) (ptr – offsetof(struct temp,ch)); printf(“Value of integer is %d”,test2->i); }

Compile and execute it.

$ cc struct_ptr.c -o struct_ptr $ ./struct_ptr Value of int is 10

Thus we can see that we were able to retrieve the pointer to the parent structure from the pointer to the member.

The same steps are used in the container_of function which is used in the linux kernel code.

/** * container_of – cast a member of a structure out to the containing structure * @ptr: the pointer to the member. * @type: the type of the container struct this is embedded in. * @member: the name of the member within the struct. * */ #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr – offsetof(type,member) );})

By passing pointer to the member of the structure in ptr and the structure type as argument type and the name of the member of which ptr is the pointer to we can retrieve the pointer to the parent structure just as we did in the example above.

Example usage in kernel code :

File leds.c

struct versatile_led { struct led_classdev cdev; u8 mask; }; static void versatile_led_set(struct led_classdev *cdev, enum led_brightness b) { struct versatile_led *led = container_of(cdev, struct versatile_led, cdev);

By passing a pointer to the cdev structure,the structure type as “versatile_led” and the member of the structure as cdev we are able to get a pointer to the structure that contains the cdev and hence get access to other members of the structure.

Category: Linux | Comments Off on Pointer to structure from its member pointer: container_of

Pointer to structure from its member pointer: container_of

In c programming, we use structures to store variables of different data types in one kind of variable. Each variable in the structure is termed as a member of the structure. The memory allocation for these members is always sequential.
Example

struct temp { int i; char ch; }

In the above structure the addresses allocated for members “i” and “ch” will be sequential in the memory.

Using this property of the structure, if we know the pointer to a member of the structure we can retrieve the pointer to the structure with the help offsetof function.
In the post “offset of” we saw how we can retrieve the offset of a member with in the structure.

As the size occupied by each data type is fixed once we know the offset of the member and its pointer, we can subtract the offset from the pointer to get a pointer to the structure.

For example in the above structure if the pointer to the “char ch” is 1000. The offset of function will return 4 for “ch” as it is after an integer in the structure.
Thus the pointer to the structure would be “1000-4 = 996”.

The same is shown in the example code below.

We allocate memory for one structure,test1, of type “temp” and assign values to “i” and “ch”.

test1 = malloc(sizeof(struct temp)); test1->i = 10; test1->ch=”h”;

Then we assign the pointer of ch to a char pointer. ptr = &(test1->ch);

Then we subtract the offset of “ch” from the pointer and assign the return value to a new pointer to a structure,test2, of type temp.

test2 = (struct temp *) (ptr – offsetof(struct temp,ch));

If the pointer assigned to test2 is the correct , we should be able to access the value of “i” using test2.
Thus we print the value of “i” using test2

printf(“%d”,test2->i);

Here is the full code

struct_ptr.c

#include#include #includestruct temp { int i; char ch; } ; main() { int size; char *ptr; struct temp *test1; struct temp *test2; test1 = malloc(sizeof(struct temp)); test1->i = 10; test1->ch=”h”; ptr = &(test1->ch); test2 = (struct temp *) (ptr – offsetof(struct temp,ch)); printf(“Value of integer is %d”,test2->i); }

Compile and execute it.

$ cc struct_ptr.c -o struct_ptr $ ./struct_ptr Value of int is 10

Thus we can see that we were able to retrieve the pointer to the parent structure from the pointer to the member.

The same steps are used in the container_of function which is used in the linux kernel code.

/** * container_of – cast a member of a structure out to the containing structure * @ptr: the pointer to the member. * @type: the type of the container struct this is embedded in. * @member: the name of the member within the struct. * */ #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr – offsetof(type,member) );})

By passing pointer to the member of the structure in ptr and the structure type as argument type and the name of the member of which ptr is the pointer to we can retrieve the pointer to the parent structure just as we did in the example above.

Example usage in kernel code :

File leds.c

struct versatile_led { struct led_classdev cdev; u8 mask; }; static void versatile_led_set(struct led_classdev *cdev, enum led_brightness b) { struct versatile_led *led = container_of(cdev, struct versatile_led, cdev);

By passing a pointer to the cdev structure,the structure type as “versatile_led” and the member of the structure as cdev we are able to get a pointer to the structure that contains the cdev and hence get access to other members of the structure.

Related Blogs

    Category: Linux | Comments Off on Pointer to structure from its member pointer: container_of

    using printk_ratelimit

    printk is used in kernel programming to log messages and is very useful while debugging the kernel programs.
    But the kernel log being though big, is restricted and unnecessary logging at times can lead to loosing relevant messages .

    Thus kernel provides a function, printk_ratelimit , to restrict the logging using which we can set a limit on the number of prints that we want our program to do.

    The limit on the number of prints is set in the file /proc/sys/kernel/printk_ratelimit_burst

    $ cat /proc/sys/kernel/printk_ratelimit_burst 10

    The printk_ratelimit function will allow 10 prints before it starts blocking the further prints.
    The printk_ratelimit, returns 1 as long as the number of prints do not exceed the limit. Once the limit is reached it starts returning 0.
    Thus the function can be used as a condition for an “if” statement to decide whether to print a message or not.
    The printk will be enabled again after a time interval in seconds mentioned in the file /proc/sys/kernel/printk_ratelimit

    $ cat /proc/sys/kernel/printk_ratelimit 5

    Which means, printk will be disabled for 5 seconds after 10 messages by the code which uses the printk_ratelimit function.

    In the example module below we put 20 prints in the init function using a for loop.
    Before each print, printk_ratelimit is called to decide whether to print or not.
    When the module gets inserted, we will notice that only the first 10 prints are printed and the rest gets suppressed.

    printk_limit.c :

    #include #include int rate_limit_init(void) { int i; for(i=0;i

    Category: Linux | Comments Off on using printk_ratelimit