Skip to content

Commit fb18fd7

Browse files
authored
Merge pull request #368 from sysprog21/params
Add module_param_cb() example
2 parents 4789288 + 2ff6b3a commit fb18fd7

3 files changed

Lines changed: 112 additions & 1 deletion

File tree

examples/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ obj-m += hello-2.o
33
obj-m += hello-3.o
44
obj-m += hello-4.o
55
obj-m += hello-5.o
6+
obj-m += hello-6.o
67
obj-m += startstop.o
78
startstop-objs := start.o stop.o
89
obj-m += chardev.o

examples/hello-6.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* hello-6.c - Demonstrates module_param_cb() callbacks.
3+
*/
4+
#include <linux/init.h>
5+
#include <linux/module.h>
6+
#include <linux/moduleparam.h>
7+
#include <linux/printk.h>
8+
9+
MODULE_LICENSE("GPL");
10+
MODULE_AUTHOR("LKMPG");
11+
MODULE_DESCRIPTION("A module_param_cb() example");
12+
13+
static int watched = 42;
14+
15+
static int watched_set(const char *val, const struct kernel_param *kp)
16+
{
17+
int ret;
18+
19+
ret = param_set_int(val, kp);
20+
if (ret)
21+
return ret;
22+
23+
pr_info("watched updated to %d\n", watched);
24+
return 0;
25+
}
26+
27+
static int watched_get(char *buffer, const struct kernel_param *kp)
28+
{
29+
int ret;
30+
31+
ret = param_get_int(buffer, kp);
32+
if (ret >= 0)
33+
pr_info("watched was read\n");
34+
35+
return ret;
36+
}
37+
38+
static const struct kernel_param_ops watched_ops = {
39+
.set = watched_set,
40+
.get = watched_get,
41+
};
42+
43+
module_param_cb(watched, &watched_ops, &watched, 0644);
44+
MODULE_PARM_DESC(watched, "An integer that logs every update");
45+
46+
static int __init hello_6_init(void)
47+
{
48+
pr_info("Hello, world 6\n");
49+
pr_info("watched starts at %d\n", watched);
50+
return 0;
51+
}
52+
53+
static void __exit hello_6_exit(void)
54+
{
55+
pr_info("Goodbye, world 6\n");
56+
}
57+
58+
module_init(hello_6_init);
59+
module_exit(hello_6_exit);

lkmpg.tex

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,38 @@ \subsection{Passing Command Line Arguments to a Module}
585585

586586
\samplec{examples/hello-5.c}
587587

588+
If you need to validate a parameter or react whenever it changes, use \cpp|module_param_cb()|.
589+
This variant takes four arguments: the parameter name, a pointer to a \cpp|struct kernel_param_ops|,
590+
an argument pointer (typically the address of the backing variable), and the sysfs permissions.
591+
The callbacks stored in \cpp|struct kernel_param_ops| let you override the \cpp|set| and \cpp|get|
592+
operations instead of relying on the default helpers such as \cpp|param_set_int()| and \cpp|param_get_int()|.
593+
With non-zero permissions, the parameter is also exposed through sysfs so the same callbacks can run after the module has already been loaded.
594+
595+
\begin{code}
596+
static int watched = 42;
597+
598+
static int watched_set(const char *val, const struct kernel_param *kp)
599+
{
600+
int ret = param_set_int(val, kp);
601+
602+
if (ret)
603+
return ret;
604+
605+
pr_info("watched updated to %d\n", watched);
606+
return 0;
607+
}
608+
609+
static const struct kernel_param_ops watched_ops = {
610+
.set = watched_set,
611+
.get = param_get_int,
612+
};
613+
614+
module_param_cb(watched, &watched_ops, &watched, 0644);
615+
\end{code}
616+
617+
The full example below also overrides \cpp|.get| so that every sysfs read is logged:
618+
\samplec{examples/hello-6.c}
619+
588620
It is recommended to experiment with the following code:
589621
\begin{verbatim}
590622
$ sudo insmod hello-5.ko mystring="bebop" myintarray=-1
@@ -611,12 +643,30 @@ \subsection{Passing Command Line Arguments to a Module}
611643
myintarray[1] = -1
612644
got 2 arguments for myintarray.
613645
614-
$ sudo rmmod hello_5
646+
$ sudo rmmod hello-5
615647
$ sudo dmesg -t | tail -1
616648
Goodbye, world 5
617649
618650
$ sudo insmod hello-5.ko mylong=hello
619651
insmod: ERROR: could not insert module hello-5.ko: Invalid parameters
652+
653+
$ sudo insmod hello-6.ko watched=7
654+
$ sudo dmesg -t | tail -3
655+
watched updated to 7
656+
Hello, world 6
657+
watched starts at 7
658+
659+
$ cat /sys/module/hello_6/parameters/watched
660+
7
661+
$ sudo dmesg -t | tail -1
662+
watched was read
663+
664+
$ echo 21 | sudo tee /sys/module/hello_6/parameters/watched
665+
21
666+
$ sudo dmesg -t | tail -1
667+
watched updated to 21
668+
669+
$ sudo rmmod hello-6
620670
\end{verbatim}
621671

622672
\subsection{Modules Spanning Multiple Files}
@@ -637,6 +687,7 @@ \subsection{Modules Spanning Multiple Files}
637687
obj-m += hello-3.o
638688
obj-m += hello-4.o
639689
obj-m += hello-5.o
690+
obj-m += hello-6.o
640691
obj-m += startstop.o
641692
startstop-objs := start.o stop.o
642693

0 commit comments

Comments
 (0)