Linux maintains a the structure of the kind "task_struct" for every process that runs in the system. This structure defined in "linux/sched.h".
It maintains various data of a process like the process id, name, memory related information etc.
While writing a module if we want to get information about the current process that is running in the kernel, we need to read the "task_struct" of the
corresponding process. The kernel provides a easy way to do this by providing a macro by the name "current", which always returns a pointer to the "task_struct" of the current executing process.
The implementation of the current pointer can change from one architecture to other, in the standard x86 architecture the pointer is read from the process stack Each process has a structure of the kind thread_info which is always stored at the end of the stack. The thread_info in turn has a pointer to the "task_struct" of the process. As the location of the thread_info is fixed in the stack, we can access it easily using the stack pointer and the stack size.
For eg: if the stack size is 8KB the 13 Least significant bits can be masked to get a pointer to the thread_info structure. The pointer to the "task_stuct" is obtained by dereferencing the member "task" of the structure which is the pointer to "task_struct".
Example for using the current pointer.
Let us try to write a module that created a proc entry "process_data" and when read, it returns the information of the current process by making use of the macro current.
To learn about proc entry creation you can refer to Creating proc entry
To be able to access "current" we will need to include the file "linux/sched.h" . In the function read_proc we print the "name" and "process id" of the
current process using "current->comm" and "current->pid" respectively. Other fields of the structure task_struct can also we referred to in the similar way.
***************************current_proc.c**************************************
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
int read_proc(char *buf,char **start,off_t offset,int count,int *eof,void *data )
{
int len=0;
len = sprintf(buf,"\n Name :%s \n Process id: %d\n ",current->comm,current->pid);
printk(KERN_INFO "Inside the proc entry");
return len;
}
void create_new_proc_entry()
{
create_proc_read_entry("process_data",0,NULL,read_proc,NULL);
}
int char_arr_init (void) {
create_new_proc_entry();
return 0;
}
void char_arr_cleanup(void) {
printk(KERN_INFO " Inside cleanup_module\n");
remove_proc_entry("process_data",NULL);
}
MODULE_LICENSE("GPL");
module_init(char_arr_init);
module_exit(char_arr_cleanup);
********************************************************************************************
**************************Makefile***************************************************
ifneq ($(KERNELRELEASE),)
obj-m := current_proc.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
*******************************************************************************
Run the following commands to see the output
$ make
$ sudo insmod current_proc.ko
$ cat /proc/process_data
Note: The output will always give process name as "cat" as that is what we are using to read the proc entry.
It maintains various data of a process like the process id, name, memory related information etc.
While writing a module if we want to get information about the current process that is running in the kernel, we need to read the "task_struct" of the
corresponding process. The kernel provides a easy way to do this by providing a macro by the name "current", which always returns a pointer to the "task_struct" of the current executing process.
The implementation of the current pointer can change from one architecture to other, in the standard x86 architecture the pointer is read from the process stack Each process has a structure of the kind thread_info which is always stored at the end of the stack. The thread_info in turn has a pointer to the "task_struct" of the process. As the location of the thread_info is fixed in the stack, we can access it easily using the stack pointer and the stack size.
For eg: if the stack size is 8KB the 13 Least significant bits can be masked to get a pointer to the thread_info structure. The pointer to the "task_stuct" is obtained by dereferencing the member "task" of the structure which is the pointer to "task_struct".
Example for using the current pointer.
Let us try to write a module that created a proc entry "process_data" and when read, it returns the information of the current process by making use of the macro current.
To learn about proc entry creation you can refer to Creating proc entry
To be able to access "current" we will need to include the file "linux/sched.h" . In the function read_proc we print the "name" and "process id" of the
current process using "current->comm" and "current->pid" respectively. Other fields of the structure task_struct can also we referred to in the similar way.
***************************current_proc.c**************************************
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
int read_proc(char *buf,char **start,off_t offset,int count,int *eof,void *data )
{
int len=0;
len = sprintf(buf,"\n Name :%s \n Process id: %d\n ",current->comm,current->pid);
printk(KERN_INFO "Inside the proc entry");
return len;
}
void create_new_proc_entry()
{
create_proc_read_entry("process_data",0,NULL,read_proc,NULL);
}
int char_arr_init (void) {
create_new_proc_entry();
return 0;
}
void char_arr_cleanup(void) {
printk(KERN_INFO " Inside cleanup_module\n");
remove_proc_entry("process_data",NULL);
}
MODULE_LICENSE("GPL");
module_init(char_arr_init);
module_exit(char_arr_cleanup);
********************************************************************************************
**************************Makefile***************************************************
ifneq ($(KERNELRELEASE),)
obj-m := current_proc.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
*******************************************************************************
Run the following commands to see the output
$ make
$ sudo insmod current_proc.ko
$ cat /proc/process_data
Note: The output will always give process name as "cat" as that is what we are using to read the proc entry.
No comments:
Post a Comment