diff --git a/01_git/Makefile b/01_git/Makefile new file mode 100644 index 0000000..000a715 --- /dev/null +++ b/01_git/Makefile @@ -0,0 +1,28 @@ +NAME = scissors + +SRC = scissors.c + +CFLAGS = -Wall -Wextra -Werror + +OBJ_DIR = obj +OBJ = $(addprefix $(OBJ_DIR)/,$(SRC:.c=.o)) + +.PHONY = all clean re + +all: $(OBJ_DIR) $(NAME) + +$(NAME): $(OBJ) + gcc $(CFLAGS) $^ -o $(NAME) + +$(addprefix $(OBJ_DIR),/%.o): %.c + gcc $(CFLAGS) $(DDFLAGS) -c $^ -o $@ + +clean: + rm -rf $(OBJ_DIR) $(NAME) + +re: + make clean + make all + +$(OBJ_DIR): + mkdir -p $@ \ No newline at end of file diff --git a/01_git/scissors.c b/01_git/scissors.c new file mode 100644 index 0000000..130c5b7 --- /dev/null +++ b/01_git/scissors.c @@ -0,0 +1,38 @@ +#include +#include +#include + +int main() +{ + char com; + int r; + + srand(time(NULL)); + + printf("Please choose: rock (r) - paper (p) - scissors (s)"); + com = getchar(); + r = rand()%3; + + if (com == 'r') printf("You choose rock, I choose " ); + if (com == 'p') printf("You choose paper, I choose " ); + if (com == 's') printf("You choose scissors, I choose "); + + if (r == 0) printf("rock.\n" ); + if (r == 1) printf("paper.\n" ); + if (r == 2) printf("scissors.\n"); + + if (com == 'r' && r == 0) printf ("Draw game.\n" ); + if (com == 'p' && r == 1) printf ("Draw game.\n" ); + if (com == 's' && r == 2) printf ("Draw game.\n" ); + + if (com == 'r' && r == 1) printf ("I win: paper beats rock.\n" ); + if (com == 'p' && r == 2) printf ("I win: scissors beats paper.\n" ); + if (com == 's' && r == 0) printf ("I win: rock beats scissors.\n" ); + + if (com == 'r' && r == 2) printf ("You win: rock beats scissors.\n" ); + if (com == 'p' && r == 0) printf ("You win: paper beats rock.\n" ); + if (com == 's' && r == 1) printf ("You win: scissors beats paper.\n" ); + + getchar(); + return 0; +} diff --git a/02_bash/devices.txt b/02_bash/devices.txt new file mode 100644 index 0000000..a79f4e9 --- /dev/null +++ b/02_bash/devices.txt @@ -0,0 +1,22 @@ + +ttyUSB :{ + +} +mmcblk :{ + +} +i2c :{ +i2c-0 +i2c-1 +i2c-2 +i2c-3 +i2c-4 +i2c-5 + +} +sd :{ +sda +sda1 +sda2 + +} \ No newline at end of file diff --git a/02_bash/hwdetech.sh b/02_bash/hwdetech.sh new file mode 100755 index 0000000..9c1b0cf --- /dev/null +++ b/02_bash/hwdetech.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +USB_UART="ttyUSB" +MMCBLK="mmcblk" +I2C="i2c" +SD="sd" + +check_device() +{ + printf "\n$1 :{\n" >> devices.txt + ls /dev/ | grep $1 >> devices.txt + printf "\n}">> devices.txt +} + + +touch devices.txt +touch tmp_devices.txt + +while [ 1 ] +do + rm devices.txt + touch devices.txt + check_device $USB_UART + check_device $MMCBLK + check_device $I2C + check_device $SD + CHK_DVC=$(diff tmp_devices.txt devices.txt) + + if [ "$CHK_DVC" != "" ] + then + cp devices.txt tmp_devices.txt + cat devices.txt + fi + + sleep 1 +done \ No newline at end of file diff --git a/02_bash/tmp_devices.txt b/02_bash/tmp_devices.txt new file mode 100644 index 0000000..a79f4e9 --- /dev/null +++ b/02_bash/tmp_devices.txt @@ -0,0 +1,22 @@ + +ttyUSB :{ + +} +mmcblk :{ + +} +i2c :{ +i2c-0 +i2c-1 +i2c-2 +i2c-3 +i2c-4 +i2c-5 + +} +sd :{ +sda +sda1 +sda2 + +} \ No newline at end of file diff --git a/03_module/README.md b/03_module/README.md new file mode 100644 index 0000000..db39346 --- /dev/null +++ b/03_module/README.md @@ -0,0 +1,16 @@ +module home work: create a simple loadable module with parameters + +Create a loadadle kernel module which should accept two integer parameters and provide: + + A sum of parameters upon driver load + A substration of parameters upon driver unload + +Info about module parameters can be found at: https://devarea.com/linux-kernel-development-kernel-module-parameters/#.YZfWcpFByV4 + +Task should be performed using buildroot+qemu approach + +The task results should contain: + + The module code + The Makefile + Dump of the kernel logs from the target system diff --git a/03_module/my_modul/Makefile b/03_module/my_modul/Makefile new file mode 100644 index 0000000..cfaf21f --- /dev/null +++ b/03_module/my_modul/Makefile @@ -0,0 +1,16 @@ +#KERNELDIR ?= ~/soft/buildroot-2021.11-rc2/output/build/linux-5.15/ +#KERNELDIR ?= ~/soft/buildroot-2021.02/output/build/linux-5.10.10/ +# KERNELDIR ?= ~/soft/buildroot-2021.02/output/host/bin/ +# KERNELDIR ?= ~/soft/buildroot-2021.11-rc2/output_oranj/build/linux-5.12.2/ + +KERNELDIR ?= ~/soft/buildroot-2021.02/temp_imeg/build/linux-5.10.10/ +ifneq ($(KERNELRELEASE),) + obj-m := modul_add.o +else + +all: + $(MAKE) CFLAGS_MODULE="-DDEBUG -DORANGE_PI_ZERO" -C $(KERNELDIR) M=$(PWD) modules +clean: + $(MAKE) -C $(KERNELDIR) M=$(PWD) clean +endif + diff --git a/03_module/my_modul/Makefile_old b/03_module/my_modul/Makefile_old new file mode 100644 index 0000000..0ba6634 --- /dev/null +++ b/03_module/my_modul/Makefile_old @@ -0,0 +1,15 @@ +ifneq ($(KERNELRELEASE),) +# kbuild part of makefile +obj-m := modul_add.o +else +# normal makefile +KDIR ?= /lib/modules/`uname -r`/build + +default: + $(MAKE) -C $(KDIR) M=$$PWD +move: + cd ../ && sudo cp -r 03_module /srv/nfs/busybox/tmp/ +clean: + $(MAKE) -C $(KDIR) M=$$PWD clean +endif + diff --git a/03_module/my_modul/kernel-log.sh b/03_module/my_modul/kernel-log.sh new file mode 100755 index 0000000..90cdae0 --- /dev/null +++ b/03_module/my_modul/kernel-log.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +# Simple script for generating logs for kernel module +# with different parameters + +echo '[Hello it`s test for first Kernel module]' +echo ' ' +echo '[With parameters]' +sleep 0.1s +insmod modul_add.ko znach_1=122 znach_2=133 +rmmod modul_add.ko + +echo ' ' +echo '[With one parameters]' +sleep 0.1s +insmod modul_add.ko znach_1=-10 +rmmod modul_add.ko + +echo ' ' +echo '[Without parameters]' +sleep 0.1s +insmod modul_add.ko +rmmod modul_add.ko diff --git a/03_module/my_modul/log_mod.txt b/03_module/my_modul/log_mod.txt new file mode 100644 index 0000000..74e7bb8 --- /dev/null +++ b/03_module/my_modul/log_mod.txt @@ -0,0 +1,17 @@ +[Hello it`s test for first Kernel module] + +[With parameters] + +[With one parameters] + +[Without parameters] + +dmesg | grep 'znach' + +[ 3230.039347] znach_1 + znach_2 = 255 +[ 3230.042907] znach_1 - znach_2 = -11 +[ 3230.164680] znach_1 + znach_2 = 0 +[ 3230.168207] znach_1 - znach_2 = -20 +[ 3230.302357] znach_1 + znach_2 = 15 +[ 3230.305929] znach_1 - znach_2 = -5 + diff --git a/03_module/my_modul/modul_add.c b/03_module/my_modul/modul_add.c new file mode 100644 index 0000000..cf2bed7 --- /dev/null +++ b/03_module/my_modul/modul_add.c @@ -0,0 +1,27 @@ +#include +#include + +static int znach_1 = 5; +static int znach_2 = 10; + +module_param(znach_1, int, S_IRUSR | S_IRGRP); +MODULE_PARM_DESC(znach_1, "the first module's parameter"); +module_param(znach_2, int, S_IRUSR | S_IRGRP); +MODULE_PARM_DESC(znach_2, "the second module's parameter"); + +int init_module(void) +{ + printk(KERN_INFO "znach_1 + znach_2 = %d\n", znach_1 + znach_2); + + return 0; +} + +void cleanup_module(void) +{ + printk(KERN_INFO "znach_1 - znach_2 = %d\n", znach_1 - znach_2); +} + +MODULE_DESCRIPTION("My simple kernel module"); +MODULE_AUTHOR("Valentin S."); +MODULE_LICENSE("GPL"); +MODULE_VERSION("0.1"); \ No newline at end of file diff --git a/04_basic_srtuct/Log_basic_struct.txt b/04_basic_srtuct/Log_basic_struct.txt new file mode 100644 index 0000000..39d3592 --- /dev/null +++ b/04_basic_srtuct/Log_basic_struct.txt @@ -0,0 +1,17 @@ +# insmod basic_struct.ko +# echo "123456" > /sys/kernel/basic_struct/list +# at /sys/kernel/basic_struct/list +-sh: at: not found +# cat /sys/kernel/basic_struct/list +123456 +# echo "Hello world 1" > /sys/kernel/basic_struct/list +# cat /sys/kernel/basic_struct/list +123456 +Hello world 1 +# echo "Hello world 2" > /sys/kernel/basic_struct/list +# echo "Hello world 3" > /sys/kernel/basic_struct/list +# cat /sys/kernel/basic_struct/list +123456 +Hello world 1 +Hello world 2 +Hello world 3 diff --git a/04_basic_srtuct/Makefile b/04_basic_srtuct/Makefile new file mode 100644 index 0000000..f984981 --- /dev/null +++ b/04_basic_srtuct/Makefile @@ -0,0 +1,11 @@ +#KERNELDIR ?= ~/Development/Embedded/exercise8/buildroot_qemu_x64_image/build/linux-5.10.7/ +KERNELDIR ?= ~/soft/buildroot-2021.11-rc2/output/build/linux-5.15/ +CFLAGS_basic_struct.o := -DDEBUG +obj-m += basic_struct.o + +all: + make -C $(KERNELDIR) M=$(PWD) modules +clean: + make -C $(KERNELDIR) M=$(PWD) clean +test: + sh test_S_mod.sh \ No newline at end of file diff --git a/04_basic_srtuct/README.md b/04_basic_srtuct/README.md new file mode 100644 index 0000000..24b5bc4 --- /dev/null +++ b/04_basic_srtuct/README.md @@ -0,0 +1,8 @@ +Basic structure homework + +Implement object with name “MyObject” which is parent of kernel_kobj. +Object should include linked_list structure. +This object should contain sysfs attribute with name “list”. +On read form attribute “list” it should show content of the objects linked list. +On write to attribute “list” it should add new string to the objects linked list. +!! Do not forget properly free all the resources during rmmod. \ No newline at end of file diff --git a/04_basic_srtuct/basic_struct.c b/04_basic_srtuct/basic_struct.c new file mode 100644 index 0000000..5719308 --- /dev/null +++ b/04_basic_srtuct/basic_struct.c @@ -0,0 +1,129 @@ +#include +#include +#include +#include +#include +#include + +// Useful link: +// https://elixir.bootlin.com/linux/latest/source/samples/kobject/kobject-example.c#L131 + +typedef struct string_list_item{ + struct list_head list; + char* stored_string; + size_t stored_string_length; +}string_list_item_t; + + +static struct kobject *list_obj; +static struct list_head string_list; + +static ssize_t add_new_string_entity(const char* buffer) +{ + string_list_item_t* p_entity = kmalloc(sizeof(string_list_item_t),GFP_KERNEL); + if(!p_entity) + return -ENOMEM; + + const size_t string_length = strlen(buffer); + const size_t string_buffer_mem_size = string_length+1; + char* string_buffer = kmalloc(string_buffer_mem_size, GFP_KERNEL); + if(!string_buffer){ + kfree(p_entity); + return -ENOMEM; + } + p_entity->stored_string = string_buffer; + + strncpy(string_buffer,buffer,string_buffer_mem_size); + p_entity->stored_string_length = string_length; + + list_add_tail(&p_entity->list,&string_list); + + return string_length; +} + +static void string_item_dtor(string_list_item_t* string_list_item){ + if(!string_list_item) + return; + + kfree(string_list_item->stored_string); + string_list_item->stored_string = NULL; + string_list_item->stored_string_length = 0; + kfree(string_list_item); +} +static void cleanup_storage(void) +{ + string_list_item_t* string_it = NULL; + struct list_head* pos, *q; + list_for_each_safe(pos,q,&string_list) + { + string_it = list_entry(pos,string_list_item_t,list); + list_del(pos); + string_item_dtor(string_it); + } + +} +static ssize_t list_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + char* buffer_pointer = buf; + ssize_t pointer_offset = 0; + string_list_item_t* list_entity_it = NULL; + list_for_each_entry(list_entity_it,&string_list,list) + { + size_t copied_data_size = list_entity_it->stored_string_length+1; + ssize_t copy_result = sprintf(buffer_pointer+ pointer_offset,"%s", list_entity_it->stored_string); + pointer_offset += copy_result; + } + pr_debug("==BASIC_STRUCT==:Called list_show with copied pointer_offset:%ld\n", pointer_offset); + return pointer_offset; +} + +static ssize_t list_store(struct kobject *kobj, + struct kobj_attribute *attr,const char *buf, size_t count) +{ + pr_debug("==BASIC_STRUCT==:Called list_store with count:%d\n", count); + ssize_t res = add_new_string_entity(buf); + if(!res) + return -EFAULT; + return count; +} + + +struct kobj_attribute list_attribute = __ATTR(list, 0660, list_show, list_store); + +static int __init simple_struct_module_init(void) +{ + int result = 0; + list_obj = kobject_create_and_add("basic_struct", kernel_kobj); + if (!list_obj){ + pr_warn("%s:%d: kobject_create_and_add failed.\n", __func__, + __LINE__); + return -ENOMEM; + } + result = sysfs_create_file(list_obj, &list_attribute.attr); + if(result){ + pr_warn("%s:%d: sysfs_create_file failed.\n", __func__, + __LINE__); + kobject_put(list_obj); + return -ENOMEM; + } + INIT_LIST_HEAD(&string_list); + + pr_debug("==BASIC_STRUCT==:Module ready\n"); + return result; +} + + +static void __exit simple_struct_module_exit(void) +{ + cleanup_storage(); + + kobject_put(list_obj); + pr_debug("==BASIC_STRUCT==:Module unloaded\n"); +} + +module_init(simple_struct_module_init); +module_exit(simple_struct_module_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Valentyn Sidorov"); \ No newline at end of file diff --git a/04_basic_srtuct/basic_struct.ko b/04_basic_srtuct/basic_struct.ko new file mode 100644 index 0000000..2d39d44 Binary files /dev/null and b/04_basic_srtuct/basic_struct.ko differ diff --git a/04_basic_srtuct/test_S_mod.sh b/04_basic_srtuct/test_S_mod.sh new file mode 100755 index 0000000..8a8f773 --- /dev/null +++ b/04_basic_srtuct/test_S_mod.sh @@ -0,0 +1,9 @@ +dmesg -c + insmod basic_struct.ko + echo "123456" > /sys/kernel/basic_struct/list + cat /sys/kernel/basic_struct/list + echo "1234567890263321564654654654679874964321356" > /sys/kernel/basic_struct/list + echo "Hello world!" > /sys/kernel/basic_struct/list + cat /sys/kernel/basic_struct/list + rmmod basic_struct.ko + dmesg \ No newline at end of file diff --git a/05_timers/README.md b/05_timers/README.md new file mode 100644 index 0000000..55b41f2 --- /dev/null +++ b/05_timers/README.md @@ -0,0 +1,10 @@ +## Homework: Linux Kernel Time Management + +1. Implement program which return absolute time in user space. +Use clock_gettime() from time.h. Try different clock id. +Find the difference. Show possible clock resolution provided by clock_getres(). + +2. Implement kernel module with API in sysfs, which returns relative +time in maximum possible resolution passed since previous read of it. +Implement kernel module with API in sysfs which returns absolute time +of previous reading with maximum resolution like ‘400.123567’ seconds. diff --git a/05_timers/kernel_module/Makefile b/05_timers/kernel_module/Makefile new file mode 100644 index 0000000..167605a --- /dev/null +++ b/05_timers/kernel_module/Makefile @@ -0,0 +1,10 @@ + +#KERNELDIR ?= ~/soft/buildroot-2021.02/output/build/linux-5.10.10/ +KERNELDIR ?= ~/soft/buildroot-2021.11-rc2/output/build/linux-5.15 +obj-m := time_attr_presenter.o + +all: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules + +clean: + $(MAKE) -C $(KERNELDIR) M=$(PWD) clean diff --git a/05_timers/kernel_module/dump.txt b/05_timers/kernel_module/dump.txt new file mode 100644 index 0000000..bb7d3f0 --- /dev/null +++ b/05_timers/kernel_module/dump.txt @@ -0,0 +1,25 @@ +# insmod /tmp/time_attr_presenter.ko +# cat /sys/kernel/time_attr_presenter/last_abs_time +-1 +# cat /sys/kernel/time_attr_presenter/last_abs_time +1639337982.183260522 +# cat /sys/kernel/time_attr_presenter/last_abs_time +1639337984.166915503 +# cat /sys/kernel/time_attr_presenter/last_relative_time +-1 +# cat /sys/kernel/time_attr_presenter/last_relative_time +0.636000000 +# cat /sys/kernel/time_attr_presenter/last_relative_time +1.812000000 +# cat /sys/kernel/time_attr_presenter/last_relative_time +0.752000000 +# rmmod time_attr_presenter.ko +time_attr_presenter: Module exited +# ls /sys/kernel/time_attr_presenter +ls: /sys/kernel/time_attr_presenter: No such file or directory + +# unix timestamps are matched with real time +date -d @1639337984.166915503 +неділя, 12 грудня 2021 21:39:44 +0200 +date -d @1639337982.183260522 +неділя, 12 грудня 2021 21:39:42 +0200 diff --git a/05_timers/kernel_module/time_attr_presenter.c b/05_timers/kernel_module/time_attr_presenter.c new file mode 100644 index 0000000..861995a --- /dev/null +++ b/05_timers/kernel_module/time_attr_presenter.c @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * 1 Implement kernel module with API in sysfs, + * which returns relative time in maximum possible + * resolution passed since previous read of it. + * 2 Implement kernel module with API in sysfs + * which returns absolute time of previous reading + * with maximum resolution like ‘400.123567’ seconds. + */ + + +#define DEBUG +#define pr_fmt(fmt) "%s: " fmt, KBUILD_MODNAME +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static ssize_t time_attr_presenter_last_abs_time_show(struct kobject *kobj, struct kobj_attribute *attr, char *buff); +static ssize_t time_attr_presenter_last_relative_time_show(struct kobject *kobj, struct kobj_attribute *attr, char *buff); +static ssize_t time_attr_presenter_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buff, size_t count); +static int time_attr_presenter_init(void); +static void time_attr_presenter_exit(void); + + +static struct kobject *time_attr_presenter_kobj; +static u64 last_read_jiffies; +static struct timespec64 last_read_time; + +static struct kobj_attribute param_abs_attribute = + __ATTR(last_abs_time, 0644, time_attr_presenter_last_abs_time_show, time_attr_presenter_store); +static struct kobj_attribute param_relative_attribute = + __ATTR(last_relative_time, 0644, time_attr_presenter_last_relative_time_show, time_attr_presenter_store); + + +static ssize_t time_attr_presenter_last_abs_time_show(struct kobject *kobj, struct kobj_attribute *attr, char *buff) +{ + if (last_read_time.tv_sec == 0 && last_read_time.tv_nsec == 0) + sprintf(buff, "-1\n"); + else + sprintf(buff, "%lli.%li\n", last_read_time.tv_sec, last_read_time.tv_nsec); + + ktime_get_real_ts64(&last_read_time); + + return strlen(buff); +} + +static ssize_t time_attr_presenter_last_relative_time_show(struct kobject *kobj, struct kobj_attribute *attr, char *buff) +{ + u64 delta = 0; + struct timespec64 ts; + + if (last_read_jiffies == 0) { + sprintf(buff, "-1\n"); + } else { + delta = get_jiffies_64() - last_read_jiffies; + jiffies_to_timespec64(delta, &ts); + sprintf(buff, "%lli.%li\n", ts.tv_sec, ts.tv_nsec); + } + last_read_jiffies = get_jiffies_64(); + + return strlen(buff); +} + + +static ssize_t time_attr_presenter_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buff, size_t count) +{ + return count; +} + + +static int time_attr_presenter_init(void) +{ + int res = 0; + + time_attr_presenter_kobj = kobject_create_and_add("time_attr_presenter", kernel_kobj); + if (!time_attr_presenter_kobj) + return -ENOMEM; + res = sysfs_create_file(time_attr_presenter_kobj, ¶m_relative_attribute.attr); + if (res) + kobject_put(time_attr_presenter_kobj); + res = sysfs_create_file(time_attr_presenter_kobj, ¶m_abs_attribute.attr); + if (res) + kobject_put(time_attr_presenter_kobj); + + last_read_jiffies = 0; + last_read_time.tv_sec = 0; + last_read_time.tv_nsec = 0; + + return res; +} + + +static void time_attr_presenter_exit(void) +{ + kobject_put(time_attr_presenter_kobj); + pr_info("Module exited\n"); +} + +module_init(time_attr_presenter_init); +module_exit(time_attr_presenter_exit); + +MODULE_AUTHOR("Valentin Sidorov "); +MODULE_DESCRIPTION("Time attribute presenter module"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("0.1"); diff --git a/05_timers/user_space/Makefile b/05_timers/user_space/Makefile new file mode 100644 index 0000000..4142923 --- /dev/null +++ b/05_timers/user_space/Makefile @@ -0,0 +1,11 @@ +CC=gcc +CFLAGS=-I. -std=c99 -D_POSIX_C_SOURCE=199309L +OUT_NAME=user-space-timers + +all: $(OUT_NAME) + +$(OUT_NAME): user_space_timers.c + $(CC) user_space_timers.c -o $(OUT_NAME) $(CFLAGS) + +clean: + /bin/rm -rf *.o a.out $(OUT_NAME) diff --git a/05_timers/user_space/dump1.txt b/05_timers/user_space/dump1.txt new file mode 100644 index 0000000..6618230 --- /dev/null +++ b/05_timers/user_space/dump1.txt @@ -0,0 +1,21 @@ +sidorov@rtx-sidorov:~/repositori/gl_kernel_procamp_2021/05_timers/user_space$ ./user_p1 +getting clock resolution... +---------------------------------------------------------------- +|clock_id |sec |nsec | +---------------------------------------------------------------- +|CLOCK_REALTIME |0 |1 | +|CLOCK_MONOTONIC |0 |1 | +|CLOCK_PROCESS_CPUTIM|0 |1 | +|CLOCK_THREAD_CPUTIME|0 |1 | +|CLOCK_BOOTTIME |0 |1 | + +getting actual clock values... +---------------------------------------------------------------- +|clock_id |sec |nsec | +---------------------------------------------------------------- +|CLOCK_REALTIME |1639735722 |665435750 | +|CLOCK_MONOTONIC |104386 |898914652 | +|CLOCK_PROCESS_CPUTIM|0 |1823907 | +|CLOCK_THREAD_CPUTIME|0 |1827586 | +|CLOCK_BOOTTIME |951996 |454427458 | + diff --git a/05_timers/user_space/user_p1 b/05_timers/user_space/user_p1 new file mode 100755 index 0000000..6be4bf4 Binary files /dev/null and b/05_timers/user_space/user_p1 differ diff --git a/05_timers/user_space/user_space_timers.c b/05_timers/user_space/user_space_timers.c new file mode 100644 index 0000000..7f23a39 --- /dev/null +++ b/05_timers/user_space/user_space_timers.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Implement program which return absolute time in user space. + * Use clock_gettime() from time.h. Try different clock id. Find the difference. + * Show possible clock resolution provided by clock_getres(). + */ + +#include +#include +#include +#include +#include + +int main(void) +{ + struct timespec real_ts, mono_ts, pcpu_ts, tcpu_ts, boot_ts; + struct timespec real_tp, mono_tp, pcpu_tp, tcpu_tp, boot_tp; + + printf("getting clock resolution...\n"); + if (clock_getres(CLOCK_REALTIME, &real_ts)) + perror(strerror(errno)); + if (clock_getres(CLOCK_MONOTONIC, &mono_ts)) + perror(strerror(errno)); + if (clock_getres(CLOCK_PROCESS_CPUTIME_ID, &pcpu_ts)) + perror(strerror(errno)); + if (clock_getres(CLOCK_THREAD_CPUTIME_ID, &tcpu_ts)) + perror(strerror(errno)); + if (clock_getres(CLOCK_BOOTTIME, &boot_ts)) + perror(strerror(errno)); + + printf("----------------------------------------------------------------\n"); + printf("|%-20.20s|%-20.20s|%-20.20s|\n", "clock_id", "sec", "nsec"); + printf("----------------------------------------------------------------\n"); + printf("|%-20.20s|%-20li|%-20li|\n", "CLOCK_REALTIME", real_ts.tv_sec, real_ts.tv_nsec); + printf("|%-20.20s|%-20li|%-20li|\n", "CLOCK_MONOTONIC", mono_ts.tv_sec, mono_ts.tv_nsec); + printf("|%-20.20s|%-20li|%-20li|\n", "CLOCK_PROCESS_CPUTIME_ID", pcpu_ts.tv_sec, pcpu_ts.tv_nsec); + printf("|%-20.20s|%-20li|%-20li|\n", "CLOCK_THREAD_CPUTIME_ID", tcpu_ts.tv_sec, tcpu_ts.tv_nsec); + printf("|%-20.20s|%-20li|%-20li|\n", "CLOCK_BOOTTIME", boot_ts.tv_sec, boot_ts.tv_nsec); + printf("\n"); + + printf("getting actual clock values...\n"); + if (clock_gettime(CLOCK_REALTIME, &real_tp)) + perror(strerror(errno)); + if (clock_gettime(CLOCK_MONOTONIC, &mono_tp)) + perror(strerror(errno)); + if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &pcpu_tp)) + perror(strerror(errno)); + if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tcpu_tp)) + perror(strerror(errno)); + if (clock_gettime(CLOCK_BOOTTIME, &boot_tp)) + perror(strerror(errno)); + + printf("----------------------------------------------------------------\n"); + printf("|%-20.20s|%-20.20s|%-20.20s|\n", "clock_id", "sec", "nsec"); + printf("----------------------------------------------------------------\n"); + printf("|%-20.20s|%-20li|%-20li|\n", "CLOCK_REALTIME", real_tp.tv_sec, real_tp.tv_nsec); + printf("|%-20.20s|%-20li|%-20li|\n", "CLOCK_MONOTONIC", mono_tp.tv_sec, mono_tp.tv_nsec); + printf("|%-20.20s|%-20li|%-20li|\n", "CLOCK_PROCESS_CPUTIME_ID", pcpu_tp.tv_sec, pcpu_tp.tv_nsec); + printf("|%-20.20s|%-20li|%-20li|\n", "CLOCK_THREAD_CPUTIME_ID", tcpu_tp.tv_sec, tcpu_tp.tv_nsec); + printf("|%-20.20s|%-20li|%-20li|\n", "CLOCK_BOOTTIME", boot_tp.tv_sec, boot_tp.tv_nsec); + printf("\n"); + + return 0; +} diff --git a/setup_orange.sh b/setup_orange.sh new file mode 100755 index 0000000..f4648a3 --- /dev/null +++ b/setup_orange.sh @@ -0,0 +1,6 @@ +#! /bin/bash +export ARCH=arm +export CROSS_COMPILE="arm-buildroot-linux-uclibcgnuebihf-" +export PATH=$PATH:~/soft/buildroot-2021.11-rc2/output_oranj/host/bin +export BUILD_KERNEL=~/soft/buildroot-2021.11-rc2/output_oranj/build/linux-5.12.2/ +export CURDIR=$(pwd)