Re: Access to kernel routine (find_task_by_pid)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Saturday 20 August 2005 10:40, canon wrote:
> I don't understand your strategy.
> In fact, the current algo looks like this :
> pid = get_pid_of_the_process_to_control ()
> while (1) {
>   if (cpu_usage_of_process (pid) * 100 > total_time_since_the_start 
> (pid) * percent) {
>     kill (SIGSTOP, pid);
>     usleep (1); usleep (1); //depend on HZ const
>     kill (SIGCONT, pid);
>   }
> }
> I don't know if it is the best solution for controlling the process but 
> it works (I have just to use the utime and starttime field of the 
> /proc/<pid>/stat file).
> Do you think that it is possible to influence the scheduling of a 
> process with the counter and priority fields in the same way with a 
> module ? Or is there better way to make a process sleep in the kernel 
> space (because I should force the process to suspend its process each ms 
> to have a fine granularity) ?

I don't know if this is the better strategies but I suggest you to implement 
it with a kernel module. I don't know if you can well control processes by 
mean of a user processes, but I'm sure that informations you can take by stat 
file can be taken from a kernel module.
I've now better understood your project and thinks seems to be really simpler 
than as I've previously understood.

I give you further suggest on implementation of timer (and related sleep 
functions). Perhaps, you can implement your program without ioctl.
The code below is an example.

With user_proc I indicate the task_struct of the process given by 
find_task_by_pid(pid)

---------------------------------------------------------------------------------------------------------------------------------
/* prog_module.c */

#define __NO_VERSION__

#if defined __KERNEL__
#   include <linux/kernel.h>
#endif

#include <linux/autoconf.h>   /* <linux/config.h> should be good too */
#if defined( CONFIG_MODVERSIONS ) && ! defined( MODVERSIONS ) 
#   define MODVERSIONS 
#endif 

#if defined( MODVERSIONS ) 
#   include <linux/modversions.h>
#endif 
 
#include <linux/module.h>
#include <linux/timer.h>

extern int create_device_file(void);
extern remove_device_file(void);

struct timer_list mtpmc_timer;
pid_t user_pid;
struc task_struct *user_proc;


int cpu_usage_exceed(void) /*IMPORTANT! you have to implement this function
{
 if (cpu_usage_of_process (user_proc) * 100 > total_time_since_the_start 
  (user_proc) * percent) 
  return 1;
 else return 0;

}

static void timer_function(unsigned long par)
{ 
 send_sig(SIGCONT, user_proc, 1);
 if (cpu_usage_exceed())
    send_sig(SIGSTOP, user_proc, 1);
 mod_timer(&timer, jiffies + par*HZ); /* jiffies is the current time. Timer 
expires after par*HZ clock ticks, that is, after par seconds */

 return;
}

int prog_init(void)
{
 create_device_file();
  init_timer(&timer);

 return 0;
}

void prog_exit(void)
{
  remove_device_file();
 del_timer(&timer); 
 return;
}

module_init(prog_init);
module_exit(prog_exit);
----------------------------------------------------------------------------------------------------------------------------
I'll explain you something:
prog_init and prog_exit are the initialization and exit function that create 
and delete the timer you've to use.
Put all in a program called prog_module.c.
Then adds the following operations before the initialization function:

static struct file_operations ops = {
 .write = write,
 .open = open,
 .release = release,
 .owner = THIS_MODULE,
};

static ssize_t write(struct file *filp, const char __user *src, 
    size_t count, loff_t *off)
{
 user_pid = ATOI(src); /* IMPORTANT! You have to substitute this function with 
the corresponding in the kernel space. I don't remember what it is.

 user_proc = find_task_by_pid(user_pid);

  timer.function = timer_function; 
  mod_timer(&timer, jiffies + num_sec*HZ);

 return 0;
}
static int mtpmc_open(struct inode *ino, struct file *filp)
{
 printk(KERN_DEBUG "open\n");
 MOD_INC_USE_COUNT;

 if (Device_Open){
  printk(KERN_DEBUG "Device already open by another user process.\n\n");
  return -EBUSY;
 }
  
 Device_Open++;

 return 0;
}

static int mtpmc_release(struct inode *ino, struct file *filp)
{
 printk(KERN_DEBUG "release\n");
 MOD_DEC_USE_COUNT;
 Device_Open--;

 return 0;
}

int create_device_file(void)
{
 major = register_chrdev(0, "prog", &ops);
 if (major<0){
  printk(KERN_DEBUG "can't get dynamic major number\n");
  return major;
 }
  
 return 0; 
}

int remove_device_file(void)
{
 int ret =  unregister_chrdev(major, "prog");
 if (ret<0){
  printk(KERN_DEBUG "error in unregister_chrdev: %d\n", ret);
  return -1;
 }

 return 0;
}
----------------------------------------------------------------------------------------------------------------------------
You have to implement the cpu_usage_exceed() function by studying the 
Scheduling procedure.

You can call this modules, after you have insmoded it, by means of a user 
program.
This have to perform only a read operation in order to pass the pid of 
monitoring process.

----------------------------------------------------------------------------------------------------------------------------
/* prog_user.c */

int main(void)
{
 char pid_par[255];
 int fd;

 printf("Opening...\n");
 fd = open("/dev/prog", O_RDWR);
 if (fd==-1){
  printf("Open failure\n");
  exit(1);
 }
 printf("Insert pid (0 to exit): ");
 scanf("%s",pid_par);
  r = read(fd, pid_par, strlen(pid_par), NULL);
}


----------------------------------------------------------------------------------------------------------------------------
I give you also a Makefile that you can use to compile the module:
----------------------------------------------------------------------------------------------------------------------------
/* Makefile */


TARGET  := prog_module
TARGET2 := prog_user
INCLUDE := -I /usr/src/linux/include
CFLAGS  := -O2 -DMODULE -D__KERNEL__  ${INCLUDE}
CC      := gcc

${TARGET}.o: ${TARGET}.c
 ${CC} ${CFLAGS} -c ${TARGET}.c

user: ${TARGET2}.c
 ${CC} ${TARGET2}.c -o ${TARGET2}
 ./${TARGET2}

.PHONY: clean

install: ${TARGET}.o
 insmod ./${TARGET}.o

uninstall: 
 rmmod ${TARGET}

clean:
 rm -rf ${TARGET}.o 
 rm -rf ${TARGET2}

---------------------------------------------------------------------------------------------------------------------
After you have completed the module  you have to run:
make /*to compile the module*/
make install /*to install the module */
make user /*to execute the user program */

To remove all:
make uninstall /* to remove the module */
make clean /* to remove objects file **/


IMPORTANT OBSERVATION!!!!!!!!!!!!!!!!!!
1. You've not to use the ioctl mechanism. I don't use it in the program I've 
described

2. I hope I'm well wrote the program as I've not tested it. Help yourself y 
studying the documentation from ULK e LDD.

3. You can also develop a module without implement a user space program but in 
this case you have to know the pid you want to monitor before inserting 
module. If so, reply me and I tell you how you can do it, reducing the size 
of the above program.

4. If you find  function that modify the amount of cpu usage of a process, 
it's better for you as you can call this instruction in the init function 
without the need to implement timers.

5. Insert the code in file and then print it. Continue studying the Chapter 
I've indicate to you (except the one treating IOCTL mechanism) and step by 
step you'll understand better what I'm wrote (and you'll find lso errors that 
I've make).

Vincenzo Mallozzi.

	

	
		
___________________________________ 
Yahoo! Mail: gratis 1GB per i messaggi e allegati da 10MB 
http://mail.yahoo.it


--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
FAQ:           http://kernelnewbies.org/faq/


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux