Search

Workqueue-2 DECLARE_WORK


Last post we say the basics of workqueue and different ways to create a workqueue.
Let us now look at an example module to create a workqueue and schedule it.

We will create a workqueue using static creation , i.e. DECLARE_WORK and then look at the runtime creation in the next post.

The below call creates a workqueue by the name workq and the function that gets scheduled in the queue is work_fn.

DECLARE_WORK(workq,workq_fn); 

We will just add a print in the work_fn function but in real workqueues this function can be used to carry out any operations that need to be scheduled.

Our work_fn will look as follows
.
void workq_fn(unsigned long arg)
{
long c;
atomic_long_set(&(workq.data),10); //Setting the data field of work_struct. 
printk(KERN_INFO "In workq function %u",atomic_long_read(&(workq.data)));
}


For this function to be executed we need to schedule the workqueue which we will implement in a proc entry such that the workqueue gets scheduled when the proc entry is read.

Let us call the proc entry as sched_work, which will be as follows

int sched_workq(char *buf,char **start,off_t offset,int len,int *eof,void *arg)
{
printk(KERN_INFO " In proc sched workq");
schedule_work(&workq);


return 0;
}

The init and exit functions only need to create and remove the proc entries respectively.

int st_init(void)

create_proc_read_entry("sched_workq",0,NULL,sched_workq,NULL);
return 0;
}
void st_exit(void)
{
remove_proc_entry("sched_workq",NULL);
}

Putting all the codes together the module will be

*********************workq_static.c*******************************
#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/init.h>
#include<linux/proc_fs.h>  //Required for creating proc entries. 
#include<linux/sched.h> 
#include <linux/workqueue.h> // Required for workqueues


void workq_fn(unsigned long); 


DECLARE_WORK(workq,workq_fn);
void workq_fn(unsigned long arg)
{
long c;
atomic_long_set(&(workq.data),10);
printk(KERN_INFO "In workq function %u",atomic_long_read(&(workq.data)));
}








int sched_workq(char *buf,char **start,off_t offset,int len,int *eof,void *arg)
{
printk(KERN_INFO " In proc sched workq");
schedule_work(&workq);


return 0;
}


int st_init(void)

create_proc_read_entry("sched_workq",0,NULL,sched_workq,NULL);
return 0;
}
void st_exit(void)
{
remove_proc_entry("sched_workq",NULL);
}
module_init(st_init);
module_exit(st_exit);
*****************************************************************


Save the above code as workq_stati.c . The makefile required for the compiling this will be

*************Makefile***************************
ifneq ($(KERNELRELEASE),) 
   obj-m := workq_static.o
else 


KERNELDIR ?= /lib/modules/$(shell uname -r)/build 


PWD := $(shell pwd)


default: 
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules  
clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
endif 
***************************************************

Compile and test the code as follows

$ make 
If there are no errors then continued

$ insmod worq_static.ko
$ cat /proc/sched_work 
$ dmesg | tail -5 
In proc sched workq
In workq function 10

The above two lines inform us that once the proc entry is read, the function gets scheduled and if the processor is free it gets executed immediately .

Note : We have used a special function "atomi_set" to assign value to variable data in work_struct because the data is of type atomic_long_t and not simple int. 



No comments:

Post a Comment