The example shows how we can change the state of a process.
Every process in linux has a task_struct for itself which stores all the relevant information about the process.
The possible states a process can have in linux are
Running or Runnable defined as TASK_RUNNING
Interruptible sleep defined as TASK_INTERRUPTIBLE
Uniterruptible sleep defined as TASK_UNINTERRUPTIBLE
Terminated task defined as TASK_STOPPED
(There are few more states that are not used often).
To look at the state of the task we can use the command
ps -eo state,comm
For eg : The ouput of the above command could be
S evince
S evinced
D gnome-terminal
S gnome-pty-helpe
S bash
R ps
The first column sigifies the state of the process where
S implies Interruptible Sleep
D implies Uninterruptible Sleep
R implies Running or Runnable.
T imples STOPPED
The second coulmn has the name of the process.
The module below creates a thread on inserting into the module kernel. The thread runs for a minute before terminating itself. The details how the thread gets created can be seen in "Kernel Threads" .
There are two proc entries that get created on inserting the module
suspend_state: On reading this proc entry the running thread's state is changed from running to Interruptible sleep
This is done by setting " thread1->state" to TASK_INTERRUPTIBLE. where thread1 is the task_struct of the thread that was created.
run_state: On reading this proc entry the thread that is in sleep state is woken up. This is done by calling wake_up_process() on thread1. Which reschedules the sleeping process.
You can read more about proc entry creation in "Creating proc entries" .
***************************process_change.c****************************************
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/semaphore.h>
#include <linux/kthread.h> // for threads
#include <linux/sched.h> // for task_struct
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/proc_fs.h>
/*char buffer[10];
int count;
struct semaphore sem;*/
static struct task_struct *thread1;
int thread_fn() {
unsigned long j0,j1;
int delay = 100*HZ;
j0 = jiffies;
j1 = j0 + delay;
while (time_before(jiffies, j1))
schedule();
printk(KERN_INFO "In thread1");
set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop())
{
schedule();
set_current_state(TASK_INTERRUPTIBLE);
}
set_current_state(TASK_RUNNING);
return 0;
}
int suspendstate(char *buf,char **start,off_t offset,int count,int *eof,void *data)
{
printk(KERN_INFO "In suspend sate");
thread1->state = TASK_INTERRUPTIBLE;
return 0;
}
int runstate(char *buf,char **start,off_t offset,int count,int *eof,void *data)
{
printk(KERN_INFO "In runsate");
wake_up_process(thread1);
return 0;
}
int thread_init (void) {
char name[15]="process1";
printk(KERN_INFO "in init");
thread1 = kthread_create(thread_fn,NULL,name);
if((thread1))
{
printk(KERN_INFO "in if");
wake_up_process(thread1);
}
create_proc_read_entry("suspend_state",0,NULL,suspendstate,NULL);
create_proc_read_entry("run_state",0,NULL,runstate,NULL);
return 0;
}
void thread_cleanup(void) {
int ret;
ret = kthread_stop(thread1);
if(!ret)
printk(KERN_INFO "Thread stopped");
}
MODULE_LICENSE("GPL");
module_init(thread_init);
module_exit(thread_cleanup);
***************************************************************************************
***************************Makefile********************************************
ifneq ($(KERNELRELEASE),)
obj-m := process_change.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
*********************************************************************************
Save the above two files with the respective names and run the following commands to see the output.
$ make
$ sudo insmod process_change.ko
$ ps -eo state,comm | grep process1 R process1
The output shows process1 is currently running
$ cat /proc/suspend_state
$ ps -eo state,comm | grep process1 S process1
After read of the proc entry suspend_state the process state changed to S, i.e. sleep state. But note the thread runs approximately for a minute so you will have to execute the "cat" command within one minute to be able to see this change.
$ cat /proc/run_state.
$ ps -eo state,comm | grep process1
R process1
After read of proc entry run_state the process state has again changed to run state.
To remove the module
$ sudo rmmod process_change
Every process in linux has a task_struct for itself which stores all the relevant information about the process.
The possible states a process can have in linux are
Running or Runnable defined as TASK_RUNNING
Interruptible sleep defined as TASK_INTERRUPTIBLE
Uniterruptible sleep defined as TASK_UNINTERRUPTIBLE
Terminated task defined as TASK_STOPPED
(There are few more states that are not used often).
To look at the state of the task we can use the command
ps -eo state,comm
For eg : The ouput of the above command could be
S evince
S evinced
D gnome-terminal
S gnome-pty-helpe
S bash
R ps
The first column sigifies the state of the process where
S implies Interruptible Sleep
D implies Uninterruptible Sleep
R implies Running or Runnable.
T imples STOPPED
The second coulmn has the name of the process.
The module below creates a thread on inserting into the module kernel. The thread runs for a minute before terminating itself. The details how the thread gets created can be seen in "Kernel Threads" .
There are two proc entries that get created on inserting the module
suspend_state: On reading this proc entry the running thread's state is changed from running to Interruptible sleep
This is done by setting " thread1->state" to TASK_INTERRUPTIBLE. where thread1 is the task_struct of the thread that was created.
run_state: On reading this proc entry the thread that is in sleep state is woken up. This is done by calling wake_up_process() on thread1. Which reschedules the sleeping process.
You can read more about proc entry creation in "Creating proc entries" .
***************************process_change.c****************************************
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/semaphore.h>
#include <linux/kthread.h> // for threads
#include <linux/sched.h> // for task_struct
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/proc_fs.h>
/*char buffer[10];
int count;
struct semaphore sem;*/
static struct task_struct *thread1;
int thread_fn() {
unsigned long j0,j1;
int delay = 100*HZ;
j0 = jiffies;
j1 = j0 + delay;
while (time_before(jiffies, j1))
schedule();
printk(KERN_INFO "In thread1");
set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop())
{
schedule();
set_current_state(TASK_INTERRUPTIBLE);
}
set_current_state(TASK_RUNNING);
return 0;
}
int suspendstate(char *buf,char **start,off_t offset,int count,int *eof,void *data)
{
printk(KERN_INFO "In suspend sate");
thread1->state = TASK_INTERRUPTIBLE;
return 0;
}
int runstate(char *buf,char **start,off_t offset,int count,int *eof,void *data)
{
printk(KERN_INFO "In runsate");
wake_up_process(thread1);
return 0;
}
int thread_init (void) {
char name[15]="process1";
printk(KERN_INFO "in init");
thread1 = kthread_create(thread_fn,NULL,name);
if((thread1))
{
printk(KERN_INFO "in if");
wake_up_process(thread1);
}
create_proc_read_entry("suspend_state",0,NULL,suspendstate,NULL);
create_proc_read_entry("run_state",0,NULL,runstate,NULL);
return 0;
}
void thread_cleanup(void) {
int ret;
ret = kthread_stop(thread1);
if(!ret)
printk(KERN_INFO "Thread stopped");
}
MODULE_LICENSE("GPL");
module_init(thread_init);
module_exit(thread_cleanup);
***************************************************************************************
***************************Makefile********************************************
ifneq ($(KERNELRELEASE),)
obj-m := process_change.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
*********************************************************************************
Save the above two files with the respective names and run the following commands to see the output.
$ make
$ sudo insmod process_change.ko
$ ps -eo state,comm | grep process1 R process1
The output shows process1 is currently running
$ cat /proc/suspend_state
$ ps -eo state,comm | grep process1 S process1
After read of the proc entry suspend_state the process state changed to S, i.e. sleep state. But note the thread runs approximately for a minute so you will have to execute the "cat" command within one minute to be able to see this change.
$ cat /proc/run_state.
$ ps -eo state,comm | grep process1
R process1
After read of proc entry run_state the process state has again changed to run state.
To remove the module
$ sudo rmmod process_change
No comments:
Post a Comment