diff --git a/.students.rst b/.students.rst index 754412ba..030d04f3 100644 --- a/.students.rst +++ b/.students.rst @@ -8,7 +8,9 @@ Lazarenko Andrii `dk81_lazarenko `_ Levytska Mariia `dk81_levytska `_ Rudiuk Bohdan `dk82_rudiuk `_ Tkachuk Yurii `dk82_tkachuk `_ +Vitalii Romakh `dk81_romakh `_ Vitalii Yurchenko `dk81_yurchenko `_ Yatsyshyn Nazar `dk82_yatsyshyn `_ Zherebchenko Roman `dk81_zherebchenko `_ ================== ========================================= + diff --git a/dk81_romakh/README.rst b/dk81_romakh/README.rst new file mode 100644 index 00000000..2f150543 --- /dev/null +++ b/dk81_romakh/README.rst @@ -0,0 +1,12 @@ +============================================= +Embedded Linux course: lab works +============================================= + +Author +------ + +* **Full name:** Romakh Vitalii +* **Organization/University:** `Igor Sikorsky Kyiv Polytechnic Institute `__ +* **Department:** `The Department of Design of Electronic Digital Equipment `__ +* **Telegram:** `@MarshallDocks `__ +* **Email:** `vitalik55575@gmail.com `__ \ No newline at end of file diff --git a/dk81_romakh/lab1/Makefile.mk b/dk81_romakh/lab1/Makefile.mk new file mode 100644 index 00000000..41c916f4 --- /dev/null +++ b/dk81_romakh/lab1/Makefile.mk @@ -0,0 +1,16 @@ +# (!) using paths with spaces may not work with Kbuild + +# this is what is used by Kbuild +obj-m += firstmod.o + +# directory containing Makefile for kernel build +KBUILDDIR ?= ~/kernel + +.PHONY: modules tidy + +# recur to the original kernel Makefile with some additions +modules: + $(MAKE) -C "$(KBUILDDIR)" M="$(PWD)" modules + +tidy: + $(MAKE) -C "$(KBUILDDIR)" M="$(PWD)" clean diff --git a/dk81_romakh/lab1/README.rst b/dk81_romakh/lab1/README.rst new file mode 100644 index 00000000..ad53063a --- /dev/null +++ b/dk81_romakh/lab1/README.rst @@ -0,0 +1,91 @@ +Лабораторна робота 1 +==================== + +Завдання: +--------- + +1. Зібрати Linux ядро з використанням BusyBox; +2. Запустити його на эмуляторі QEMU; +3. Створити модуль ядра, щоб після завершення модуль друкував в лог поточне значення jiffies і час в секундах, який пройшов від init до exit. + +Виконання роботи: +----------------- + +Збірка Linux-ядра +~~~~~~~~~~~~~~~~~ +Спочатку необхідно встановити QEMU ``sudo pacman -S base-devel qemu qemu-arch-extra bc cpio``. + +Перед зборкою ядра сконфігурувати його за допомогою ``make menuconfig``. +Запустити зборку ядра ``make -j5 vmlinux``, для 4 ядер. +Для ядра необхідно додатково зібрати bzImage ``make -j5 bzImage``. + +Зібрати BusyBox +~~~~~~~~~~~~~~~ +BusyBox - це мінімалістичний набір базових команд реалізований у вигляді одного виконуваного файлу. + +.. code-block:: + make -j5 CRYPT_AVAILABLE=n install + +Після чого необхідно перейти в папку *_install* та створити файл папки */proc* */sys* і надати їм необхідні права доступу: + +.. code-block:: + cd _install + mkdir proc + mkdir sys + chmod 555 proc + chmod 555 sys + +Також необхідно створити файл */init*б він має мати права для виконання. Ядро виконає цей файл одразу ж після першочергових етапів запуску. + +Створити з цієї диреткорії архів ``find . -print0 | cpio --null --owner=0:0 -ov --format=newc | gzip -9 > ../../initramfs.cpio.gz`` + + +Збірка модуля +~~~~~~~~~~~~~ + +Для того щоб зібрати модуль я створив *Makefile*, в директорії з мейкфайлом та вихідним файлом необхідно виконати ``make modules`` + + +Запуск ядра +~~~~~~~~~~~ +Запуск відбувається на віртуальній машині QEMU +.. code-block:: + qemu-system-x86_64 -m 256M -smp 4 -kernel "./arch/x86/boot/bzImage" -initrd "./initramfs.cpio.gz" \ -append "console=ttyS0" -nographic \ + -drive file=fat:rw:../Documents/Labs/Lab1,format=raw,media=disk + + + +Робота з модулем ядра +~~~~~~~~~~~~~~~~~~~~~ + +Створемо папку ``mkdir /mnt`` +Змонтуємо перший розділ диска``mount -t vfat /dev/sda1 /mnt`` +Завантажемо зібраний модуль: + +.. code-block:: + insmod /mnt/firstmod.ko username="VitaliiR" + #вивід + #[ 668.002165] Hello, VitaliiR! + #[ 668.002165] jiffies = 4295335315 + + +Перевіремо список завантажених модулей +.. code-block:: + lsmod + #вивід + #firstmod 16384 0 - Live 0xffffffffc029a000 (O) + +Вигрузити модуль ``rmmod firstmod`` + .. code-block:: + rmmod firstmod + #вивід + #[ 674.202917] Long live the Kernel! + #[ 674.202917] Time from init to exit = 6sec + + +Висновок +-------- + +Під час виконання лабораторної роботи я навчився збирати Linux ядро. +Запускати його на віртуальній машині та завантажувати власні модулі. +Запуск на віртуальній машині використовують для запровадження безпечного тестування модуля. \ No newline at end of file diff --git a/dk81_romakh/lab1/firstmod.c b/dk81_romakh/lab1/firstmod.c new file mode 100644 index 00000000..27a1ef08 --- /dev/null +++ b/dk81_romakh/lab1/firstmod.c @@ -0,0 +1,47 @@ +#include // required by all modules +#include // required for sysinfo +#include // used by module_init, module_exit macros +#include // where jiffies and its helpers reside +#include + +MODULE_DESCRIPTION("Basic module demo: init, deinit, printk, jiffies"); +MODULE_AUTHOR("Vitalii Romakh"); +MODULE_VERSION("0.1"); +MODULE_LICENSE("GPL"); // this affects the kernel behavior + +static char *username = NULL; + +module_param(username, charp, 0000); +MODULE_PARM_DESC(username, "A character string"); + +/* + * module_param(foo, int, 0000) + * The first param is the parameters name + * The second param is it's data type + * The final argument is the permissions bits, + * for exposing parameters in sysfs (if non-zero) at a later stage. + */ + +static unsigned long jiffies_init_time; +static struct timespec64 jiffies_value; // 64-bit signed int to store the seconds + + +static int __init firstmod_init(void) +{ + jiffies_init_time = jiffies; + if (username == NULL) { + username = "$username"; + } + printk(KERN_INFO "Hello, %s!\njiffies = %lu\n", username, jiffies_init_time); + return 0; +} + +static void __exit firstmod_exit(void) +{ + jiffies_to_timespec64(jiffies - jiffies_init_time, &jiffies_value); + printk(KERN_INFO "Long live the Kernel!\nTime from init to exit = %usec\n", + jiffies_value.tv_sec); +} + +module_init(firstmod_init); +module_exit(firstmod_exit); diff --git a/dk81_romakh/src/main.c b/dk81_romakh/src/main.c new file mode 100644 index 00000000..d1b87ea3 --- /dev/null +++ b/dk81_romakh/src/main.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 + * All rights reserved. + */ + +#include "rand.h" + +int main(void) +{ + int result = GAME_OK; + char button_pressed; + + while (1) { + if (result == GAME_ERROR) { + printf("Game Error!\n"); + break; + } else { + printf("Press enter to retry, q to exit\n"); + scanf("%c", &button_pressed); + + if (button_pressed == 'q') { + break; + } + result = game(); + } + } + return 0; +} diff --git a/dk81_romakh/src/rand.c b/dk81_romakh/src/rand.c new file mode 100644 index 00000000..fac9d0a5 --- /dev/null +++ b/dk81_romakh/src/rand.c @@ -0,0 +1,80 @@ +#include "rand.h" + +int game(void) +{ + int player_score = -1; + int computer_score = -1; + + // Data for pseudo animations + int player_sequence[PS_ANIM_SEQ_LENGTH]; + int computer_sequence[PS_ANIM_SEQ_LENGTH]; + + init_sequence(player_sequence, PS_ANIM_SEQ_LENGTH); + init_sequence(computer_sequence, PS_ANIM_SEQ_LENGTH); + + player_score = player_sequence[PS_ANIM_SEQ_LENGTH - 1]; + computer_score = computer_sequence[PS_ANIM_SEQ_LENGTH - 1]; + + pseudo_animation("Human", player_sequence, PS_ANIM_SEQ_LENGTH); + pseudo_animation("Computer", computer_sequence, PS_ANIM_SEQ_LENGTH); + + if (player_score == -1 || computer_score == -1) { + return GAME_ERROR; + } + + if (player_score > computer_score) { + printf("Human win!\n"); + } else if (player_score < computer_score) { + printf("Computer win\n"); + } else { + printf("Draw!\n"); + } + + return GAME_OK; +} + +void init_sequence(int seq[], int seq_length) +{ + for (int i = 0; i < seq_length; i++) { + seq[i] = rand() % MAX_RND; + } +} + +int delay(long milli_seconds) +{ + struct timespec ts; + int res; + + if (milli_seconds < 0) { + return -1; + } + + ts.tv_sec = milli_seconds / 1000; + ts.tv_nsec = (milli_seconds % 1000) * 1000000; + + do { + res = nanosleep(&ts, &ts); + } while (res); + + return res; +} + +void pseudo_animation(const char *message, int seq[], int seq_length) +{ + printf("%s:\n\n", message); + + const int upper_delay_ms = 250; + const int lower_delay_ms = 125; + for (int i = 0; i < seq_length - 1; i++) { + char num_ascii = seq[i] + '0'; + // Get up on one line \033[A and remove all from it \33[2K + printf("\033[A\33[2K%c\n", num_ascii); + + int delay_ms = + (rand() % (upper_delay_ms - lower_delay_ms + 1)) + + lower_delay_ms; + delay(delay_ms); + } + + printf("\033[A\33[2K%c\n", (seq[seq_length - 1] + '0')); +} diff --git a/dk81_romakh/src/rand.h b/dk81_romakh/src/rand.h new file mode 100644 index 00000000..18e3cfca --- /dev/null +++ b/dk81_romakh/src/rand.h @@ -0,0 +1,19 @@ +#include +#include +#include +//#include + +#define PS_ANIM_SEQ_LENGTH 6 +#define MAX_RND 9 + + + +enum GAME_STATUS{ + GAME_OK = 0, + GAME_ERROR = 1 +}; + +int game(void); +void init_sequence(int seq[], int seq_length); +int delay(long milli_seconds); +void pseudo_animation(const char *message, int seq[], int seq_length);