Skip to content
Open

lab1 #289

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .students.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ Lazarenko Andrii `dk81_lazarenko </dk81_lazarenko>`_
Levytska Mariia `dk81_levytska </dk81_levytska>`_
Rudiuk Bohdan `dk82_rudiuk </dk82_rudiuk>`_
Tkachuk Yurii `dk82_tkachuk </dk82_tkachuk>`_
Vitalii Romakh `dk81_romakh </dk81_romakh>`_
Vitalii Yurchenko `dk81_yurchenko </dk81_yurchenko>`_
Yatsyshyn Nazar `dk82_yatsyshyn </dk82_yatsyshyn>`_
Zherebchenko Roman `dk81_zherebchenko </dk81_zherebchenko>`_
================== =========================================

12 changes: 12 additions & 0 deletions dk81_romakh/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
=============================================
Embedded Linux course: lab works
=============================================

Author
------

* **Full name:** Romakh Vitalii
* **Organization/University:** `Igor Sikorsky Kyiv Polytechnic Institute <https://kpi.ua/en>`__
* **Department:** `The Department of Design of Electronic Digital Equipment <http://keoa.kpi.ua/go/cPath/0_20737/lang/en/index.htm?language=en>`__
* **Telegram:** `@MarshallDocks <https://t.me/MarshallDocks>`__
* **Email:** `[email protected] <mailto:[email protected]>`__
16 changes: 16 additions & 0 deletions dk81_romakh/lab1/Makefile.mk
Original file line number Diff line number Diff line change
@@ -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
91 changes: 91 additions & 0 deletions dk81_romakh/lab1/README.rst
Original file line number Diff line number Diff line change
@@ -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 ядро.
Запускати його на віртуальній машині та завантажувати власні модулі.
Запуск на віртуальній машині використовують для запровадження безпечного тестування модуля.
47 changes: 47 additions & 0 deletions dk81_romakh/lab1/firstmod.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include <linux/module.h> // required by all modules
#include <linux/kernel.h> // required for sysinfo
#include <linux/init.h> // used by module_init, module_exit macros
#include <linux/jiffies.h> // where jiffies and its helpers reside
#include <linux/time.h>

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);
28 changes: 28 additions & 0 deletions dk81_romakh/src/main.c
Original file line number Diff line number Diff line change
@@ -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;
}
80 changes: 80 additions & 0 deletions dk81_romakh/src/rand.c
Original file line number Diff line number Diff line change
@@ -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'));
}
19 changes: 19 additions & 0 deletions dk81_romakh/src/rand.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
//#include <unistd.h>

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