-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Volodymyr.savchenko #85
base: master
Are you sure you want to change the base?
Changes from 1 commit
c3cccc7
bd2b237
2da617e
8d41347
3b0a8e4
80a6c6e
b81d145
d4204cb
4e1b134
4ade49c
7247b87
c3886d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
obj-m+=my_time.o | ||
|
||
all: | ||
make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules | ||
|
||
clean: | ||
make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules | ||
|
||
# obj-m+=mymodule.o | ||
|
||
# all: | ||
# make -C $(BUILD_KERNEL) M=$(PWD) modules | ||
# clean: | ||
# make -C $(BUILD_KERNEL) M=$(PWD) clean |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
>>>>>>>>>>>>> cmd | ||
~/projects/training/linux/task_06$ insmod my_time.ko | ||
~/projects/training/linux/task_06$ cat /sys/class/myTime/info | ||
Now: 2018-11-18 17-08-47 | ||
Time in sec from previous read:: 27 | ||
Last read time (absolute): 2018-11-18 17-08-20 | ||
~/projects/training/linux/task_06$ cat /sys/class/myTime/info | ||
Now: 2018-11-18 17-08-53 | ||
Time in sec from previous read:: 5 | ||
Last read time (absolute): 2018-11-18 17-08-48 | ||
~/projects/training/linux/task_06$ echo 1 > /sys/class/myTime/set | ||
~/projects/training/linux/task_06$ echo 1 > /sys/class/myTime/info | ||
bash: echo: помилка запису: Помилка введення-виведення | ||
~/projects/training/linux/task_06$ echo 1.25 > /sys/class/myTime/set | ||
~/projects/training/linux/task_06$ dmesg | ||
~/projects/training/linux/task_06$ echo 6.25 > /sys/class/myTime/set | ||
~/projects/training/linux/task_06$ echo "asdfg" > /sys/class/myTime/set | ||
~/projects/training/linux/task_06$ echo 2000 > /sys/class/myTime/set | ||
~/projects/training/linux/task_06$ rmmod my_time | ||
~/projects/training/linux/task_06$ dmesg > dmesg_timer.log | ||
>>>>>>>>>>>> dmesg | ||
[16049.777041] my_time: loaded | ||
[16055.021400] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16060.136940] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16065.252663] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16070.368201] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16075.483406] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16077.372713] my_time: call my_show | ||
[16077.372716] my_time: call my_show | ||
[16080.598918] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16083.145935] my_time: call my_show | ||
[16083.145938] my_time: call my_show | ||
[16085.715049] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16090.839449] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16095.945524] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16101.061111] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16106.176742] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16111.292365] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16116.407726] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16121.523508] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16126.639240] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16131.754892] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16134.670267] my_time: call my_store | ||
[16134.670271] my_time: call my_store, invalid value of the delay: 1 | ||
[16134.670273] my_time: call my_store, using default: 5000 | ||
[16139.683559] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16144.799318] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16149.914480] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16155.030519] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16160.146208] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16165.261137] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16170.376691] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16170.747261] my_time: call my_store | ||
[16170.747265] my_time: call my_store, invalid value of the delay: 1 | ||
[16170.747267] my_time: call my_store, using default: 5000 | ||
[16175.748901] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16180.863551] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16185.979096] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16187.781406] my_time: call my_store | ||
[16187.781410] my_time: call my_store, invalid value of the delay: 6 | ||
[16187.781412] my_time: call my_store, using default: 5000 | ||
[16192.885044] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16198.001295] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16203.116160] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16206.525201] my_time: call my_store | ||
[16206.525204] my_time: call my_store, can't read delay value! | ||
[16211.557390] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16216.672922] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16221.788650] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16226.903444] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16232.019826] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16237.135404] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16242.250068] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16247.365837] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16252.481467] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16257.597082] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16262.712189] my_time: call my_timer_callback, delay: 5000 [ms] | ||
[16265.054779] my_time: call my_store | ||
[16267.060387] my_time: call my_timer_callback, delay: 2000 [ms] | ||
[16269.075265] my_time: call my_timer_callback, delay: 2000 [ms] | ||
[16271.089700] my_time: call my_timer_callback, delay: 2000 [ms] | ||
[16273.104114] my_time: call my_timer_callback, delay: 2000 [ms] | ||
[16275.117559] my_time: call my_timer_callback, delay: 2000 [ms] | ||
[16277.131978] my_time: call my_timer_callback, delay: 2000 [ms] | ||
[16279.145903] my_time: call my_timer_callback, delay: 2000 [ms] | ||
[16280.351788] my_time: removed |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
|
||
#include <linux/init.h> | ||
#include <linux/module.h> | ||
#include <linux/device.h> | ||
#include <linux/err.h> | ||
#include <linux/ctype.h> | ||
#include <linux/string.h> | ||
#include <linux/jiffies.h> | ||
#include <linux/time.h> | ||
#include <linux/timer.h> | ||
|
||
#define DEFAULT_DELAY_IN_MS 5000 | ||
#define MIN_DELAY_IN_MS 100 | ||
|
||
static unsigned long jiffies_stamp; | ||
static unsigned long jiffies_now; | ||
static unsigned long delta_in_ms; | ||
static struct timespec epoch_now; | ||
static struct timer_list my_timer; | ||
|
||
|
||
static void mod_my_timer(void) | ||
{ | ||
mod_timer(&my_timer, jiffies + msecs_to_jiffies(delta_in_ms)); | ||
} | ||
|
||
static void my_timer_callback(unsigned long data) | ||
{ | ||
pr_info("my_time: call %s, delay: %lu [ms]\n", __func__, delta_in_ms); | ||
mod_my_timer(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like there is no way to stop this timer. |
||
} | ||
|
||
static ssize_t my_show(struct class *class, struct class_attribute *attr, | ||
char *buf) | ||
{ | ||
struct tm last_read; | ||
|
||
pr_info("my_time: call %s", __func__); | ||
|
||
jiffies_now = jiffies; | ||
|
||
if (time_before(jiffies_stamp, jiffies_now)) { | ||
getnstimeofday(&epoch_now); | ||
time_to_tm(epoch_now.tv_sec, 0, &last_read); | ||
pr_info("my_time: call %s ", __func__); | ||
sprintf(buf, "Now: %04ld-%02d-%02d %02d-%02d-%02d\n", | ||
1900 + last_read.tm_year, 1 + last_read.tm_mon, last_read.tm_mday, | ||
last_read.tm_hour, last_read.tm_min, last_read.tm_sec); | ||
sprintf(buf + strlen(buf), "Time in sec from previous read:: %lu\n", | ||
(jiffies_now - jiffies_stamp) / HZ); | ||
time_to_tm(epoch_now.tv_sec - (jiffies_now - jiffies_stamp) / HZ, 0, | ||
&last_read); | ||
sprintf(buf + strlen(buf), | ||
"Last read time (absolute): %04ld-%02d-%02d %02d-%02d-%02d\n", | ||
1900 + last_read.tm_year, 1 + last_read.tm_mon, last_read.tm_mday, | ||
last_read.tm_hour, last_read.tm_min, last_read.tm_sec); | ||
jiffies_stamp = jiffies_now; | ||
} else { | ||
sprintf(buf, "Overflow detected. Re-init now."); | ||
jiffies_stamp = jiffies_now; | ||
} | ||
return strlen(buf); | ||
} | ||
|
||
static ssize_t my_store(struct class *class, struct class_attribute *attr, | ||
const char *buf, size_t count) | ||
{ | ||
int ret_value; | ||
|
||
pr_info("my_time: call %s", __func__); | ||
ret_value = sscanf(buf, "%lu", &delta_in_ms); | ||
|
||
if (ret_value != 1) { | ||
pr_info("my_time: call %s, can't read delay value!\n", __func__); | ||
} | ||
|
||
if (delta_in_ms < MIN_DELAY_IN_MS) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
In this case the timer will be restarted with default value, correct? |
||
pr_info("my_time: call %s, invalid value of the delay: %lu\n", | ||
__func__, delta_in_ms); | ||
delta_in_ms = DEFAULT_DELAY_IN_MS; | ||
pr_info("my_time: call %s, using default: %lu\n", __func__, | ||
delta_in_ms); | ||
} | ||
|
||
mod_my_timer(); | ||
return count; | ||
} | ||
|
||
|
||
static ssize_t my_info(struct class *class, struct class_attribute *attr, | ||
char *buf) | ||
{ | ||
|
||
pr_info("my_time: call %s", __func__); | ||
sprintf(buf, "Time delay now is: %ld [ms]", delta_in_ms); | ||
return strlen(buf); | ||
} | ||
|
||
|
||
struct class_attribute class_attr_tm = { | ||
.attr = { .name = "info", .mode = 0666 }, | ||
.show = my_show, | ||
}; | ||
|
||
|
||
struct class_attribute class_attr_set = { | ||
.attr = { .name = "set", .mode = 0666 }, | ||
.show = my_info, | ||
.store = my_store | ||
}; | ||
|
||
|
||
static struct class *attr_class; | ||
|
||
|
||
static int my_init(void) | ||
{ | ||
int ret; | ||
|
||
jiffies_stamp = jiffies; | ||
|
||
attr_class = class_create(THIS_MODULE, "myTime"); | ||
|
||
if (attr_class == NULL) { | ||
pr_err("my_time: error creating sysfs class\n"); | ||
return -ENOMEM; | ||
} | ||
|
||
ret = class_create_file(attr_class, &class_attr_tm); | ||
if (ret) { | ||
pr_err("my_time: error creating sysfs class attribute\n"); | ||
class_destroy(attr_class); | ||
return ret; | ||
} | ||
|
||
|
||
ret = class_create_file(attr_class, &class_attr_set); | ||
if (ret) { | ||
pr_err("my_time: error creating sysfs class attribute\n"); | ||
class_destroy(attr_class); | ||
return ret; | ||
} | ||
delta_in_ms = DEFAULT_DELAY_IN_MS; | ||
setup_timer(&my_timer, my_timer_callback, 0); | ||
mod_my_timer(); | ||
|
||
pr_info("my_time: loaded\n"); | ||
return 0; | ||
} | ||
|
||
static void my_exit(void) | ||
{ | ||
del_timer(&my_timer); | ||
class_remove_file(attr_class, &class_attr_tm); | ||
class_remove_file(attr_class, &class_attr_set); | ||
|
||
class_destroy(attr_class); | ||
|
||
pr_info("my_time: removed\n"); | ||
} | ||
|
||
module_init(my_init); | ||
module_exit(my_exit); | ||
|
||
MODULE_AUTHOR("Volodymyr Savchenko <[email protected]>"); | ||
MODULE_DESCRIPTION("Linux kernel time example`"); | ||
MODULE_LICENSE("GPL"); | ||
MODULE_VERSION("0.1"); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering how this can help in debugging?
It reflects just a fact of callback call, but what parameters were pased into?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
value of delay (5000) is passed into.