Tuesday, April 8, 2014

Passing arguments to kernel module

Why we need argument to a prgram?

       Some program needs input to process it, we can give inputs in two ways 1) passing command line argument, 2) getting the inputs dynamically during the execution.

Let’s see passing the argument to user space program first then will move on to kernel module


How do I pass arguments to user space program?
       Below is simple C code to accept the command line arguments.
#include<stdio.h>
int main(int argc, char *argv[]){
        printf("\n count : %d argument[0] %s\n", argc, argv[0]);
        return 0;
}
o/p:
gcc test.c
 ./a.out
 count : 1 argument[0] ./a.out

What is argc and argv?
       argc refers to the number of command line arguments passed in, which includes the actual name of the program, as invoked by the user. argv contains the actual arguments, starting with index 1. Index 0 is the program name.
So, if you ran your program like this:
./program hello world
Then:
·         argc would be 3.
·         argv[0] would be "./program".
·         argv[1] would be "hello".
·         argv[2] would be "world".

Can I change the name of argc and argv?
       Yes, you can change name, but not the type.
Can I pass int or float or any other data type argument to main?
       No, you can only pass string as a arguments, if you want float data or int data then use string manipulation functions. Here is simple conversion.
#include<stdio.h>
int main(int argc, char *argv[]){
        int a;
        float b;
        sscanf(argv[1], "%d", &a);
        sscanf(argv[2], "%f", &b);
        printf("int : %d \n", a);
        printf("float : %f \n", b);
        return 0;
}
o/p:
gcc test.c
./a.out 5 5.5
int : 5
float : 5.500000

How many arguments main can accept?
                We can pass no arguments or one or two arguments in main, but not more than two. Without argc we can’t get the argv.

Can I change the argv or argc paramaters value after I pass it to main?
                Well, No. but you can do it by doing some hack. but in kernel module we can change it, we see this later.


Can I change the argv or argc paramaters value after I pass it to main?
                Well, No. but you can do it by doing some hack. but in kernel module we can change it, we see this later.


Why we need argument to a kernel module?
Some modules may need input to process it, we can give inputs in two ways 1) passing command line argument, 2) getting the inputs from user applications.

Let’s see passing the command line argument to kernel module

How do I pass arguments to kernel module?
       Below is simple C code to accept the command line arguments.
#include<linux/module.h>
#include<linux/moduleparam.h>  //for module_param
#include<linux/kernel.h>       //for printk
#include<linux/init.h>         //for __init __exit

int myint;
module_param(myint, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
MODULE_PARM_DESC(myint, "An integer");

char *mystring;
module_param(mystring, charp, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
MODULE_PARM_DESC(mystring, "string");

int myintarray[10], argc;
module_param_array(myintarray, int, &argc ,S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
MODULE_PARM_DESC(myintarray, "An integer array");


static int __init mymodule_init(void)
{
 printk ("My int : %d\n", myint);
 printk ("My String : %s\n", mystring);
 printk ("My array[0] : %d\n", myintarray[0]);
 printk ("My array[1] : %d\n", myintarray[1]);
 printk ("My argc: %d\n", argc);
        return 0;
}

static void __exit mymodule_exit(void)
{
 printk ("Unloading my module.\n");
        return;
}

module_init(mymodule_init);
module_exit(mymodule_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("R.Kalimuthu");

Output:

insmod test_module.ko myint=100 mystring="kalimuthu" myintarray=10,20,30
dmesg

My int : 100
My String : kalimuthu
My array[0] : 10
My array[1] : 20
My argc: 3

modinfo test_module.ko
filename:       test_module.ko
author:         R.Kalimuthu
license:        GPL
depends:
vermagic:       2.6.34.6 SMP preempt mod_unload
parm:           myint:An integer (int)
parm:           mystring:string (charp)
parm:           myintarray:An integer array (array of int)



Can I pass any type of data to kernel module?
       Yes, unlike user space program, we can pass any type. The above example accepts int or string or array.
What are the arguments we pass to module_param()?
       Module_param() is defined in moduleparam.h, so we need to include that as well. Module_param() gets three arguments 1) variable name, 2) variable type 3) permission for the variables.
module_param(myint, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);

What is “charp” in module_param()?
       To accept string as arguments we use charp type.
 module_param(mystring, charp, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);

What are the arguments we pass to module_param_array()?
       Module_param_array() gets four arguments 1) variable name, 2) variable type 3) index 4) permission.
module_param_array(myintarray, int, &argc ,S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);

Why we need MODULE_PARAM_DESC()?
       MODULE_PARAM_DESC() prints the description of the variable in modinfo.
parm:           myint:An integer (int)
parm:           mystring:string (charp)
parm:           myintarray:An integer array (array of int)

Why we need to set the permission for the variables?
        In kernel module, we have option to change the parameter value dynamically, I mean after you pass the parameter, if you want to change you can do it. for that you need to set the permission.
cd /sys/module/test_module/parameters/
ls
myint  myintarray  mystring
cat myint
100
echo 200 > myint
cat myint
200





No comments: