Skip to content
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

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
14 changes: 14 additions & 0 deletions 06-TimeManagement/Makefile
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
86 changes: 86 additions & 0 deletions 06-TimeManagement/dmesg_timer.log
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

call my_store

I'm wondering how this can help in debugging?
It reflects just a fact of callback call, but what parameters were pased into?

Copy link
Author

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.

[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
170 changes: 170 additions & 0 deletions 06-TimeManagement/my_time.c
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();
Copy link
Contributor

Choose a reason for hiding this comment

The 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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (delta_in_ms < MIN_DELAY_IN_MS) {

In this case the timer will be restarted with default value, correct?
So the previous delay period successfully set before would be dropped.

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");