diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..95606e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +**/.vscode +**/*.out +**/*.o +**/*.cmd +**/*.symvers +**/*.order +**/*.ko +**/*.mod +**/*.mod.c \ No newline at end of file diff --git a/01_git/scissors/a.out b/01_git/scissors/a.out new file mode 100755 index 0000000..b3b5166 Binary files /dev/null and b/01_git/scissors/a.out differ diff --git a/01_git/scissors/main.c b/01_git/scissors/main.c new file mode 100644 index 0000000..62bd6b4 --- /dev/null +++ b/01_git/scissors/main.c @@ -0,0 +1,81 @@ +#include +#include +#include + +#define UNDEFINED 0 +#define ERROR -1 + +#define ROCK 'r' +#define PAPER 'p' +#define SCISSORS 's' + +bool is_command_valid(char command) { + return command == ROCK || command == PAPER || command == SCISSORS; +} + +char get_computer_command() { + int command = rand() % 3; + switch (command) { + case 0: + return ROCK; + case 1: + return PAPER; + case 2: + return SCISSORS; + default: + return UNDEFINED; + } +} + +char define_winner(char computer_command, char user_command) { + if (!is_command_valid(computer_command) || !is_command_valid(user_command)) { + return ERROR; + } + + if (computer_command == user_command) { + return UNDEFINED; + } else if (computer_command == ROCK && user_command == SCISSORS) { + return computer_command; + } else if (computer_command == PAPER && user_command == ROCK) { + return computer_command; + } else if (computer_command == SCISSORS && user_command == PAPER) { + return computer_command; + } else { + return user_command; + } +} + +char* get_command_name(char command) { + if (command == ROCK) { + return "rock"; + } else if (command == PAPER) { + return "paper"; + } else if (command == SCISSORS) { + return "scissors"; + } else { + return ""; + } +} + +int main() { + printf("Please choose: rock (r) - paper (p) - scissors (s)\n"); + char computer_command = get_computer_command(); + char user_command = getchar(); + + char* computer_command_name = get_command_name(computer_command); + char* user_command_name = get_command_name(user_command); + + printf("You choose %s, I choose %s\n", user_command_name, computer_command_name); + + char winner_command = define_winner(computer_command, user_command); + + if (winner_command == computer_command) { + printf("I win: %s beats %s\n", computer_command_name, user_command_name); + } else if (winner_command == user_command) { + printf("You win: %s beats %s\n", user_command_name, computer_command_name); + } else { + printf("Draw\n"); + } + + return 0; +} \ No newline at end of file diff --git a/01_git/scissors/run.sh b/01_git/scissors/run.sh new file mode 100755 index 0000000..dd40724 --- /dev/null +++ b/01_git/scissors/run.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +rm a.out +gcc main.c +./a.out \ No newline at end of file diff --git a/02_bash/hwdetect/echo b/02_bash/hwdetect/echo new file mode 100644 index 0000000..e69de29 diff --git a/02_bash/hwdetect/hwdetect.sh b/02_bash/hwdetect/hwdetect.sh new file mode 100755 index 0000000..0ba1eb4 --- /dev/null +++ b/02_bash/hwdetect/hwdetect.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +devices=`lsusb` +while : +do + sleep 1 + + new_devices=`lsusb` + + # discover disconnected devices + for device in $devices + do + is_present=0 + for new_device in $new_devices; + do + if [ $new_device = $device ] + then + is_present=1 + break + fi + done + + if [ $is_present -eq 0 ] + then + echo "Disconnected: $device" + fi + done + + # discover connected devices + for new_device in $new_devices + do + is_present=0 + for device in $devices; + do + if [ $new_device = $device ] + then + is_present=1 + break + fi + done + + if [ $is_present -eq 0 ] + then + echo "Connected: $new_device" + fi + done + + devices=$new_devices +done \ No newline at end of file diff --git a/03_module/.gitignore b/03_module/.gitignore new file mode 100644 index 0000000..7d4c27d --- /dev/null +++ b/03_module/.gitignore @@ -0,0 +1,6 @@ +module/*.cmd +module/*.mod* +module/*.ko +/module/*.o +module/Module.symvers +module/modules.order \ No newline at end of file diff --git a/03_module/README.md b/03_module/README.md new file mode 100644 index 0000000..739d55a --- /dev/null +++ b/03_module/README.md @@ -0,0 +1,15 @@ +## 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/logs_dump.txt b/03_module/logs_dump.txt new file mode 100644 index 0000000..24bd65f --- /dev/null +++ b/03_module/logs_dump.txt @@ -0,0 +1,309 @@ +Linux version 5.10.7 (anatolii@anatolii-TM1707) (x86_64-buildroot-linux-uclibc-gcc.br_real (Buildroot 2021.02.7) 9.4.0, GNU ld (GNU Binutils) 2.35.2) #1 SMP Mon Nov 22 11:28:54 EET 2021 +Command line: rootwait root=/dev/vda console=tty1 console=ttyS0 +x86/fpu: x87 FPU will use FXSAVE +BIOS-provided physical RAM map: +BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable +BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved +BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved +BIOS-e820: [mem 0x0000000000100000-0x0000000007fdcfff] usable +BIOS-e820: [mem 0x0000000007fdd000-0x0000000007ffffff] reserved +BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved +NX (Execute Disable) protection: active +SMBIOS 2.8 present. +DMI: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014 +tsc: Fast TSC calibration using PIT +tsc: Detected 1991.997 MHz processor +e820: update [mem 0x00000000-0x00000fff] usable ==> reserved +e820: remove [mem 0x000a0000-0x000fffff] usable +last_pfn = 0x7fdd max_arch_pfn = 0x400000000 +MTRR default type: write-back +MTRR fixed ranges enabled: + 00000-9FFFF write-back + A0000-BFFFF uncachable + C0000-FFFFF write-protect +MTRR variable ranges enabled: + 0 base 0080000000 mask FF80000000 uncachable + 1 disabled + 2 disabled + 3 disabled + 4 disabled + 5 disabled + 6 disabled + 7 disabled +x86/PAT: Configuration [0-7]: WB WC UC- UC WB WP UC- WT +found SMP MP-table at [mem 0x000f5aa0-0x000f5aaf] +ACPI: Early table checksum verification disabled +ACPI: RSDP 0x00000000000F58C0 000014 (v00 BOCHS ) +ACPI: RSDT 0x0000000007FE1550 000034 (v01 BOCHS BXPCRSDT 00000001 BXPC 00000001) +ACPI: FACP 0x0000000007FE1404 000074 (v01 BOCHS BXPCFACP 00000001 BXPC 00000001) +ACPI: DSDT 0x0000000007FE0040 0013C4 (v01 BOCHS BXPCDSDT 00000001 BXPC 00000001) +ACPI: FACS 0x0000000007FE0000 000040 +ACPI: APIC 0x0000000007FE1478 000078 (v01 BOCHS BXPCAPIC 00000001 BXPC 00000001) +ACPI: HPET 0x0000000007FE14F0 000038 (v01 BOCHS BXPCHPET 00000001 BXPC 00000001) +ACPI: WAET 0x0000000007FE1528 000028 (v01 BOCHS BXPCWAET 00000001 BXPC 00000001) +ACPI: Local APIC address 0xfee00000 +Zone ranges: + DMA [mem 0x0000000000001000-0x0000000000ffffff] + DMA32 [mem 0x0000000001000000-0x0000000007fdcfff] + Normal empty +Movable zone start for each node +Early memory node ranges + node 0: [mem 0x0000000000001000-0x000000000009efff] + node 0: [mem 0x0000000000100000-0x0000000007fdcfff] +Zeroed struct page in unavailable ranges: 133 pages +Initmem setup node 0 [mem 0x0000000000001000-0x0000000007fdcfff] +On node 0 totalpages: 32635 + DMA zone: 64 pages used for memmap + DMA zone: 21 pages reserved + DMA zone: 3998 pages, LIFO batch:0 + DMA32 zone: 448 pages used for memmap + DMA32 zone: 28637 pages, LIFO batch:7 +ACPI: PM-Timer IO Port: 0x608 +ACPI: Local APIC address 0xfee00000 +ACPI: LAPIC_NMI (acpi_id[0xff] dfl dfl lint[0x1]) +IOAPIC[0]: apic_id 0, version 32, address 0xfec00000, GSI 0-23 +ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl) +ACPI: INT_SRC_OVR (bus 0 bus_irq 5 global_irq 5 high level) +ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level) +ACPI: INT_SRC_OVR (bus 0 bus_irq 10 global_irq 10 high level) +ACPI: INT_SRC_OVR (bus 0 bus_irq 11 global_irq 11 high level) +ACPI: IRQ0 used by override. +ACPI: IRQ5 used by override. +ACPI: IRQ9 used by override. +ACPI: IRQ10 used by override. +ACPI: IRQ11 used by override. +Using ACPI (MADT) for SMP configuration information +ACPI: HPET id: 0x8086a201 base: 0xfed00000 +smpboot: Allowing 1 CPUs, 0 hotplug CPUs +[mem 0x08000000-0xfffbffff] available for PCI devices +Booting paravirtualized kernel on bare hardware +clocksource: refined-jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645519600211568 ns +setup_percpu: NR_CPUS:64 nr_cpumask_bits:64 nr_cpu_ids:1 nr_node_ids:1 +percpu: Embedded 42 pages/cpu s133528 r8192 d30312 u2097152 +pcpu-alloc: s133528 r8192 d30312 u2097152 alloc=1*2097152 +pcpu-alloc: [0] 0 +Built 1 zonelists, mobility grouping on. Total pages: 32102 +Kernel command line: rootwait root=/dev/vda console=tty1 console=ttyS0 +Dentry cache hash table entries: 16384 (order: 5, 131072 bytes, linear) +Inode-cache hash table entries: 8192 (order: 4, 65536 bytes, linear) +mem auto-init: stack:off, heap alloc:off, heap free:off +Memory: 111304K/130540K available (8195K kernel code, 900K rwdata, 1740K rodata, 896K init, 2212K bss, 18976K reserved, 0K cma-reserved) +SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 +rcu: Hierarchical RCU implementation. +rcu: RCU restricting CPUs from NR_CPUS=64 to nr_cpu_ids=1. +rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies. +rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1 +NR_IRQS: 4352, nr_irqs: 48, preallocated irqs: 16 +Console: colour VGA+ 80x25 +printk: console [tty1] enabled +printk: console [ttyS0] enabled +ACPI: Core revision 20200925 +clocksource: hpet: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604467 ns +APIC: Switch to symmetric I/O mode setup +..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1 +clocksource: tsc-early: mask: 0xffffffffffffffff max_cycles: 0x396d4bf570c, max_idle_ns: 881590425443 ns +Calibrating delay loop (skipped), value calculated using timer frequency.. 3983.99 BogoMIPS (lpj=7967988) +pid_max: default: 32768 minimum: 301 +Mount-cache hash table entries: 512 (order: 0, 4096 bytes, linear) +Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes, linear) +Last level iTLB entries: 4KB 0, 2MB 0, 4MB 0 +Last level dTLB entries: 4KB 0, 2MB 0, 4MB 0, 1GB 0 +Spectre V1 : Mitigation: usercopy/swapgs barriers and __user pointer sanitization +Spectre V2 : Mitigation: Full AMD retpoline +Spectre V2 : Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch +Speculative Store Bypass: Vulnerable +Freeing SMP alternatives memory: 24K +smpboot: CPU0: AMD QEMU Virtual CPU version 2.5+ (family: 0x6, model: 0x6, stepping: 0x3) +Performance Events: PMU not available due to virtualization, using software events only. +rcu: Hierarchical SRCU implementation. +smp: Bringing up secondary CPUs ... +smp: Brought up 1 node, 1 CPU +smpboot: Max logical packages: 1 +smpboot: Total of 1 processors activated (3983.99 BogoMIPS) +devtmpfs: initialized +random: get_random_u32 called from bucket_table_alloc.isra.0+0x75/0x160 with crng_init=0 +clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns +futex hash table entries: 256 (order: 2, 16384 bytes, linear) +NET: Registered protocol family 16 +thermal_sys: Registered thermal governor 'step_wise' +thermal_sys: Registered thermal governor 'user_space' +cpuidle: using governor ladder +ACPI: bus type PCI registered +PCI: Using configuration type 1 for base access +ACPI: Added _OSI(Module Device) +ACPI: Added _OSI(Processor Device) +ACPI: Added _OSI(3.0 _SCP Extensions) +ACPI: Added _OSI(Processor Aggregator Device) +ACPI: Added _OSI(Linux-Dell-Video) +ACPI: Added _OSI(Linux-Lenovo-NV-HDMI-Audio) +ACPI: Added _OSI(Linux-HPI-Hybrid-Graphics) +ACPI: 1 ACPI AML tables successfully acquired and loaded +ACPI: Interpreter enabled +ACPI: (supports S0 S3 S5) +ACPI: Using IOAPIC for interrupt routing +PCI: Using host bridge windows from ACPI; if necessary, use "pci=nocrs" and report a bug +ACPI: Enabled 2 GPEs in block 00 to 0F +ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff]) +acpi PNP0A03:00: _OSC: OS supports [ASPM ClockPM Segments HPX-Type3] +acpi PNP0A03:00: fail to add MMCONFIG information, can't access extended PCI configuration space under this bridge. +PCI host bridge to bus 0000:00 +pci_bus 0000:00: root bus resource [io 0x0000-0x0cf7 window] +pci_bus 0000:00: root bus resource [io 0x0d00-0xffff window] +pci_bus 0000:00: root bus resource [mem 0x000a0000-0x000bffff window] +pci_bus 0000:00: root bus resource [mem 0x08000000-0xfebfffff window] +pci_bus 0000:00: root bus resource [mem 0x100000000-0x17fffffff window] +pci_bus 0000:00: root bus resource [bus 00-ff] +pci 0000:00:00.0: [8086:1237] type 00 class 0x060000 +pci 0000:00:01.0: [8086:7000] type 00 class 0x060100 +pci 0000:00:01.1: [8086:7010] type 00 class 0x010180 +pci 0000:00:01.1: reg 0x20: [io 0xc0a0-0xc0af] +pci 0000:00:01.1: legacy IDE quirk: reg 0x10: [io 0x01f0-0x01f7] +pci 0000:00:01.1: legacy IDE quirk: reg 0x14: [io 0x03f6] +pci 0000:00:01.1: legacy IDE quirk: reg 0x18: [io 0x0170-0x0177] +pci 0000:00:01.1: legacy IDE quirk: reg 0x1c: [io 0x0376] +pci 0000:00:01.3: [8086:7113] type 00 class 0x068000 +pci 0000:00:01.3: quirk: [io 0x0600-0x063f] claimed by PIIX4 ACPI +pci 0000:00:01.3: quirk: [io 0x0700-0x070f] claimed by PIIX4 SMB +pci 0000:00:02.0: [1234:1111] type 00 class 0x030000 +pci 0000:00:02.0: reg 0x10: [mem 0xfd000000-0xfdffffff pref] +pci 0000:00:02.0: reg 0x18: [mem 0xfebd0000-0xfebd0fff] +pci 0000:00:02.0: reg 0x30: [mem 0xfebc0000-0xfebcffff pref] +pci 0000:00:03.0: [1af4:1000] type 00 class 0x020000 +pci 0000:00:03.0: reg 0x10: [io 0xc080-0xc09f] +pci 0000:00:03.0: reg 0x14: [mem 0xfebd1000-0xfebd1fff] +pci 0000:00:03.0: reg 0x20: [mem 0xfe000000-0xfe003fff 64bit pref] +pci 0000:00:03.0: reg 0x30: [mem 0xfeb80000-0xfebbffff pref] +pci 0000:00:04.0: [1af4:1001] type 00 class 0x010000 +pci 0000:00:04.0: reg 0x10: [io 0xc000-0xc07f] +pci 0000:00:04.0: reg 0x14: [mem 0xfebd2000-0xfebd2fff] +pci 0000:00:04.0: reg 0x20: [mem 0xfe004000-0xfe007fff 64bit pref] +pci_bus 0000:00: on NUMA node 0 +ACPI: PCI Interrupt Link [LNKA] (IRQs 5 *10 11) +ACPI: PCI Interrupt Link [LNKB] (IRQs 5 *10 11) +ACPI: PCI Interrupt Link [LNKC] (IRQs 5 10 *11) +ACPI: PCI Interrupt Link [LNKD] (IRQs 5 10 *11) +ACPI: PCI Interrupt Link [LNKS] (IRQs *9) +pci 0000:00:02.0: vgaarb: setting as boot VGA device +pci 0000:00:02.0: vgaarb: VGA device added: decodes=io+mem,owns=io+mem,locks=none +pci 0000:00:02.0: vgaarb: bridge control possible +vgaarb: loaded +SCSI subsystem initialized +libata version 3.00 loaded. +ACPI: bus type USB registered +usbcore: registered new interface driver usbfs +usbcore: registered new interface driver hub +usbcore: registered new device driver usb +Advanced Linux Sound Architecture Driver Initialized. +PCI: Using ACPI for IRQ routing +PCI: pci_cache_line_size set to 64 bytes +e820: reserve RAM buffer [mem 0x0009fc00-0x0009ffff] +e820: reserve RAM buffer [mem 0x07fdd000-0x07ffffff] +clocksource: Switched to clocksource tsc-early +pnp: PnP ACPI init +pnp 00:00: Plug and Play ACPI device, IDs PNP0303 (active) +pnp 00:01: Plug and Play ACPI device, IDs PNP0f13 (active) +pnp 00:02: [dma 2] +pnp 00:02: Plug and Play ACPI device, IDs PNP0700 (active) +pnp 00:03: Plug and Play ACPI device, IDs PNP0400 (active) +pnp 00:04: Plug and Play ACPI device, IDs PNP0501 (active) +pnp 00:05: Plug and Play ACPI device, IDs PNP0b00 (active) +pnp: PnP ACPI: found 6 devices +clocksource: acpi_pm: mask: 0xffffff max_cycles: 0xffffff, max_idle_ns: 2085701024 ns +NET: Registered protocol family 2 +tcp_listen_portaddr_hash hash table entries: 256 (order: 0, 4096 bytes, linear) +TCP established hash table entries: 1024 (order: 1, 8192 bytes, linear) +TCP bind hash table entries: 1024 (order: 2, 16384 bytes, linear) +TCP: Hash tables configured (established 1024 bind 1024) +UDP hash table entries: 256 (order: 1, 8192 bytes, linear) +UDP-Lite hash table entries: 256 (order: 1, 8192 bytes, linear) +NET: Registered protocol family 1 +pci_bus 0000:00: resource 4 [io 0x0000-0x0cf7 window] +pci_bus 0000:00: resource 5 [io 0x0d00-0xffff window] +pci_bus 0000:00: resource 6 [mem 0x000a0000-0x000bffff window] +pci_bus 0000:00: resource 7 [mem 0x08000000-0xfebfffff window] +pci_bus 0000:00: resource 8 [mem 0x100000000-0x17fffffff window] +pci 0000:00:01.0: PIIX3: Enabling Passive Release +pci 0000:00:00.0: Limiting direct PCI/PCI transfers +pci 0000:00:01.0: Activating ISA DMA hang workarounds +pci 0000:00:02.0: Video device with shadowed ROM at [mem 0x000c0000-0x000dffff] +PCI: CLS 0 bytes, default 64 +workingset: timestamp_bits=62 max_order=15 bucket_order=0 +Block layer SCSI generic (bsg) driver version 0.4 loaded (major 254) +io scheduler mq-deadline registered +io scheduler kyber registered +input: Power Button as /devices/LNXSYSTM:00/LNXPWRBN:00/input/input0 +ACPI: Power Button [PWRF] +PCI Interrupt Link [LNKC] enabled at IRQ 11 +PCI Interrupt Link [LNKD] enabled at IRQ 10 +Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled +00:04: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A +bochs-drm 0000:00:02.0: vgaarb: deactivate vga console +Console: switching to colour dummy device 80x25 +[drm] Found bochs VGA, ID 0xb0c0. +[drm] Framebuffer size 16384 kB @ 0xfd000000, mmio @ 0xfebd0000. +[TTM] Zone kernel: Available graphics memory: 55794 KiB +[TTM] Initializing pool allocator +[TTM] Initializing DMA pool allocator +[drm] Found EDID data blob. +[drm] Initialized bochs-drm 1.0.0 20130925 for 0000:00:02.0 on minor 0 +fbcon: bochs-drmdrmfb (fb0) is primary device +Console: switching to colour frame buffer device 128x48 +bochs-drm 0000:00:02.0: [drm] fb0: bochs-drmdrmfb frame buffer device +virtio_blk virtio1: [vda] 122880 512-byte logical blocks (62.9 MB/60.0 MiB) +vda: detected capacity change from 0 to 62914560 +ata_piix 0000:00:01.1: version 2.13 +scsi host0: ata_piix +scsi host1: ata_piix +ata1: PATA max MWDMA2 cmd 0x1f0 ctl 0x3f6 bmdma 0xc0a0 irq 14 +ata2: PATA max MWDMA2 cmd 0x170 ctl 0x376 bmdma 0xc0a8 irq 15 +ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver +ehci-pci: EHCI PCI platform driver +uhci_hcd: USB Universal Host Controller Interface driver +usbcore: registered new interface driver usb-storage +i8042: PNP: PS/2 Controller [PNP0303:KBD,PNP0f13:MOU] at 0x60,0x64 irq 1,12 +serio: i8042 KBD port at 0x60,0x64 irq 1 +serio: i8042 AUX port at 0x60,0x64 irq 12 +usbcore: registered new interface driver usbhid +usbhid: USB HID core driver +input: AT Translated Set 2 keyboard as /devices/platform/i8042/serio0/input/input1 +NET: Registered protocol family 10 +Segment Routing with IPv6 +sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver +NET: Registered protocol family 17 +IPI shorthand broadcast: enabled +sched_clock: Marking stable (981626737, 18660054)->(1003751110, -3464319) +ALSA device list: + No soundcards found. +ata2.01: NODEV after polling detection +ata2.00: ATAPI: QEMU DVD-ROM, 2.5+, max UDMA/100 +scsi 1:0:0:0: CD-ROM QEMU QEMU DVD-ROM 2.5+ PQ: 0 ANSI: 5 +tsc: Refined TSC clocksource calibration: 1991.968 MHz +clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x396d1603e08, max_idle_ns: 881590726352 ns +clocksource: Switched to clocksource tsc +input: ImExPS/2 Generic Explorer Mouse as /devices/platform/i8042/serio1/input/input3 +EXT4-fs (vda): mounting ext2 file system using the ext4 subsystem +EXT4-fs (vda): mounted filesystem without journal. Opts: (null) +VFS: Mounted root (ext2 filesystem) readonly on device 254:0. +devtmpfs: mounted +Freeing unused kernel image (initmem) memory: 896K +Write protecting the kernel read-only data: 12288k +Freeing unused kernel image (text/rodata gap) memory: 2044K +Freeing unused kernel image (rodata/data gap) memory: 308K +Run /sbin/init as init process + with arguments: + /sbin/init + with environment: + HOME=/ + TERM=linux +EXT4-fs (vda): warning: mounting unchecked fs, running e2fsck is recommended +EXT4-fs (vda): re-mounted. Opts: (null) +ext2 filesystem being remounted at / supports timestamps until 2038 (0x7fffffff) +random: fast init done +random: dd: uninitialized urandom read (512 bytes read) +random: mktemp: uninitialized urandom read (6 bytes read) +random: mktemp: uninitialized urandom read (6 bytes read) +hello: loading out-of-tree module taints kernel. +hello: module license 'unspecified' taints kernel. +Disabling lock debugging due to kernel taint +Hi world! 6 +Bye world! 2 diff --git a/03_module/module/Makefile b/03_module/module/Makefile new file mode 100644 index 0000000..44db04f --- /dev/null +++ b/03_module/module/Makefile @@ -0,0 +1,10 @@ +KERNELDIR ?= /home/anatolii/Projects/buildroot/buildroot-2021.02.7/output/build/linux-5.10.7/ + +obj-m := hello.o + +all: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules + +clean: + $(MAKE) -C $(KERNELDIR) M=$(PWD) clean + diff --git a/03_module/module/hello.c b/03_module/module/hello.c new file mode 100644 index 0000000..d1f1853 --- /dev/null +++ b/03_module/module/hello.c @@ -0,0 +1,20 @@ +#include +#include +#include + +static int a=0; +module_param(a,int,0660); + +static int b=0; +module_param(b,int,0660); + +int init_module(void) +{ + printk(KERN_INFO "Hi world! %d\n", a + b); + return 0; +} + +void cleanup_module(void) { + printk(KERN_INFO "Bye world! %d\n", a - b); +} + diff --git a/04_basic_struct/.gitignore b/04_basic_struct/.gitignore new file mode 100644 index 0000000..7d4c27d --- /dev/null +++ b/04_basic_struct/.gitignore @@ -0,0 +1,6 @@ +module/*.cmd +module/*.mod* +module/*.ko +/module/*.o +module/Module.symvers +module/modules.order \ No newline at end of file diff --git a/04_basic_struct/README.md b/04_basic_struct/README.md new file mode 100644 index 0000000..445d6dc --- /dev/null +++ b/04_basic_struct/README.md @@ -0,0 +1,7 @@ +## 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. diff --git a/04_basic_struct/module/Makefile b/04_basic_struct/module/Makefile new file mode 100644 index 0000000..f9daf33 --- /dev/null +++ b/04_basic_struct/module/Makefile @@ -0,0 +1,11 @@ +KERNELDIR ?= /home/anatolii/Projects/buildroot/buildroot-2021.02.7/output/build/linux-5.10.7/ + +obj-m := hello.o +CFLAGS_hello.o := -DDEBUG + +all: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules + +clean: + $(MAKE) -C $(KERNELDIR) M=$(PWD) clean + diff --git a/04_basic_struct/module/hello.c b/04_basic_struct/module/hello.c new file mode 100644 index 0000000..bc79d60 --- /dev/null +++ b/04_basic_struct/module/hello.c @@ -0,0 +1,111 @@ +#define pr_fmt(fmt) "%s: " fmt, KBUILD_MODNAME + +#include // Core header for loading LKMs into the kernel +#include +#include +#include +#include +#include +#include + +struct node { + char *value; + struct list_head list_member; +}; + +static LIST_HEAD(nodeHead); + +static void add_node(char *value, struct list_head *head) +{ + pr_debug("---> %s", __func__); + struct node *nodePtr = kmalloc(sizeof(struct node), GFP_KERNEL); + + if (nodePtr == NULL) + pr_err("Node creation error"); + nodePtr->value = value; + INIT_LIST_HEAD(&nodePtr->list_member); + list_add(&(nodePtr->list_member), head); + pr_debug("---< %s", __func__); +} + +static ssize_t list_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + pr_debug("---> %s", __func__); + struct list_head *iter; + struct node *nodePtr; + + int bufSize = 0; + + list_for_each(iter, &nodeHead) { + nodePtr = list_entry(iter, struct node, list_member); + strcpy(buf + bufSize, nodePtr->value); + bufSize += strlen(nodePtr->value); + pr_debug("Node copy to buf: %s", nodePtr->value); + } + pr_debug("---< %s", __func__); + return bufSize; +} + +static ssize_t list_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + pr_debug("---> %s size_t: %ld", __func__, count); + char *value = kcalloc(count, sizeof(char), GFP_KERNEL); + + memcpy(value, buf, count); + pr_debug("value created: %ld", strlen(value)); + add_node(value, &nodeHead); + pr_debug("---< %s", __func__); + return count; +} + +static struct kobj_attribute list_attribute = + __ATTR(list, 0664, list_show, list_store); + +static struct kobject *my_kobj; + +static int hello_init(void) +{ + pr_debug("---> %s", __func__); + int res = 0; + + my_kobj = kobject_create_and_add("MyObject", kernel_kobj); + if (!my_kobj) { + pr_err("Object was not created"); + return -ENOMEM; + } + res = sysfs_create_file(my_kobj, &list_attribute.attr); + if (res) { + pr_err("Attribute for Object was not created"); + kobject_put(my_kobj); + } + pr_debug("---< %s", __func__); + return res; +} + +static void hello_exit(void) +{ + pr_debug("---> %s", __func__); + struct node *nodePtr; + struct node *tmp; + + list_for_each_entry_safe(nodePtr, tmp, &nodeHead, list_member) { + pr_debug("Clean node: %s", nodePtr->value); + kfree(nodePtr->value); + list_del(&(nodePtr->list_member)); + kfree(nodePtr); + } + pr_debug("List_empty: %d", list_empty(&nodeHead)); + kobject_put(my_kobj); + + pr_debug("---< %s", __func__); +} + +module_init(hello_init); +module_exit(hello_exit); + +MODULE_AUTHOR("Anatolii Berchanov "); +MODULE_DESCRIPTION("Basic data structures module"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("0.1"); 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/module/Makefile b/05_timers/module/Makefile new file mode 100644 index 0000000..701321b --- /dev/null +++ b/05_timers/module/Makefile @@ -0,0 +1,11 @@ +KERNELDIR ?= /home/anatolii/Projects/buildroot/buildroot-2021.02.7/output/build/linux-5.10.7/ + +obj-m := time_module.o +CFLAGS_time_module.o := -DDEBUG + +all: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules + +clean: + $(MAKE) -C $(KERNELDIR) M=$(PWD) clean + diff --git a/05_timers/module/logs.txt b/05_timers/module/logs.txt new file mode 100644 index 0000000..0006f12 --- /dev/null +++ b/05_timers/module/logs.txt @@ -0,0 +1,66 @@ +# pwd +/sys/kernel +# insmod /home/user/time_module.ko +# cd time/ +# ls -l +total 0 +-r--r--r-- 1 root root 4096 Dec 8 10:24 absolute +-rw-rw-r-- 1 root root 4096 Dec 8 10:24 relative +# cat relative +# cat relative +Delta: 2453508690 +# cat relative +Delta: 2571053950 +# cat relative +Delta: 4401452740 +# echo "reset" > relative +# cat relative +# cat relative +Delta: 1044315750 +# +# cat absolute +Absolute: 0.000000000 +# cat absolute +Absolute: 1638959167.971671309 +# cat absolute +Absolute: 1638959169.873894859 +# echo "reset" > absolute +-sh: can't create absolute: Permission denied +# dmesg +time_module: ---< time_exit +time_module: ---> time_init +time_module: ---< time_init +time_module: ---> relative_show +time_module: Previous time initialization: 3862439910169 +time_module: ---< relative_show +time_module: ---> relative_show +Delta: 2453508690 +time_module: Previous time updated: 3864893418859 +time_module: ---< relative_show +time_module: ---> relative_show +Delta: 2571053950 +time_module: Previous time updated: 3867464472809 +time_module: ---< relative_show +time_module: ---> relative_show +Delta: 4401452740 +time_module: Previous time updated: 3871865925549 +time_module: ---< relative_show +time_module: ---> relative_store size_t: 6 +time_module: Previous time reset: 3871865925549 +time_module: ---< relative_store +time_module: ---> relative_show +time_module: Previous time initialization: 3887672222959 +time_module: ---< relative_show +time_module: ---> relative_show +Delta: 1044315750 +time_module: Previous time updated: 3888716538709 +time_module: ---< relative_show +time_module: ---> absolute_show +Absolute: 0.000000000 +time_module: ---< absolute_show +time_module: ---> absolute_show +Absolute: 1638959167.971671309 +time_module: ---< absolute_show +time_module: ---> absolute_show +Absolute: 1638959169.873894859 +# diff --git a/05_timers/module/time_module.c b/05_timers/module/time_module.c new file mode 100644 index 0000000..67f1d33 --- /dev/null +++ b/05_timers/module/time_module.c @@ -0,0 +1,120 @@ +#define pr_fmt(fmt) "%s: " fmt, KBUILD_MODNAME + +#include // Core header for loading LKMs into the kernel +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static ktime_t prev_time = 0; +static ktime_t prev_abs_time = 0; + +static ssize_t relative_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + pr_debug("---> %s", __func__); + + if (prev_time == 0) { + prev_time = ktime_get(); + pr_debug("Previous time initialization: %llu", prev_time); + } else { + ktime_t cur_time = ktime_get(); + ktime_t delta = ktime_sub(cur_time, prev_time); + printk(KERN_INFO "Delta: %llu", delta); + prev_time = cur_time; + pr_debug("Previous time updated: %llu", prev_time); + } + + pr_debug("---< %s", __func__); + return 0; +} + +static ssize_t relative_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + pr_debug("---> %s size_t: %ld", __func__, count); + + if (sysfs_streq(buf, "reset")) { + pr_debug("Previous time reset: %llu", prev_time); + prev_time = 0; + } + + pr_debug("---< %s", __func__); + return count; +} + +static ssize_t absolute_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + struct timespec64 ts; + pr_debug("---> %s", __func__); + ts = ktime_to_timespec64(prev_abs_time); + printk(KERN_INFO "Absolute: %lld.%09ld", ts.tv_sec, ts.tv_nsec); + prev_abs_time = ktime_get_real(); + pr_debug("---< %s", __func__); + return 0; +} + +static ssize_t absolute_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + pr_debug("---> %s size_t: %ld", __func__, count); + + pr_debug("---< %s", __func__); + return count; +} + +static struct kobj_attribute relative_attribute = + __ATTR(relative, 0664, relative_show, relative_store); + +static struct kobj_attribute absolute_attribute = + __ATTR(absolute, 0444, absolute_show, absolute_store); + +static struct kobject *time_kobj; + +static int time_init(void) +{ + int res = 0; + + pr_debug("---> %s", __func__); + + time_kobj = kobject_create_and_add("time", kernel_kobj); + if (!time_kobj) { + pr_err("Object was not created"); + return -ENOMEM; + } + res = sysfs_create_file(time_kobj, &relative_attribute.attr); + if (res) { + pr_err("Attribute for Object was not created"); + kobject_put(time_kobj); + } + res = sysfs_create_file(time_kobj, &absolute_attribute.attr); + if (res) { + pr_err("Attribute for Object was not created"); + kobject_put(time_kobj); + } + pr_debug("---< %s", __func__); + return res; +} + +static void time_exit(void) +{ + pr_debug("---> %s", __func__); + + kobject_put(time_kobj); + + pr_debug("---< %s", __func__); +} + +module_init(time_init); +module_exit(time_exit); + +MODULE_AUTHOR("Anatolii Berchanov "); +MODULE_DESCRIPTION("Time module"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("0.1"); diff --git a/05_timers/userspace/logs.txt b/05_timers/userspace/logs.txt new file mode 100644 index 0000000..08d0e9a --- /dev/null +++ b/05_timers/userspace/logs.txt @@ -0,0 +1,55 @@ +Clock - CLOCK_REALTIME + time sec 1638696837 + time nsec 265112465 + res sec 0 + rs nsec 1 +Clock - CLOCK_REALTIME_ALARM + time sec 1638696837 + time nsec 265126215 + res sec 0 + rs nsec 1 +Clock - CLOCK_REALTIME_COARSE + time sec 1638696837 + time nsec 263821244 + res sec 0 + rs nsec 4000000 +Clock - CLOCK_TAI + time sec 1638696837 + time nsec 265145840 + res sec 0 + rs nsec 1 +Clock - CLOCK_MONOTONIC + time sec 34890 + time nsec 523876764 + res sec 0 + rs nsec 1 +Clock - CLOCK_MONOTONIC_COARSE + time sec 34890 + time nsec 522528835 + res sec 0 + rs nsec 4000000 +Clock - CLOCK_MONOTONIC_RAW + time sec 34889 + time nsec 761360235 + res sec 0 + rs nsec 1 +Clock - CLOCK_BOOTTIME + time sec 165057 + time nsec 208177337 + res sec 0 + rs nsec 1 +Clock - CLOCK_BOOTTIME_ALARM + time sec 165057 + time nsec 208205837 + res sec 0 + rs nsec 1 +Clock - CLOCK_PROCESS_CPUTIME_ID + time sec 3 + time nsec 274211482 + res sec 0 + rs nsec 1 +Clock - CLOCK_THREAD_CPUTIME_ID + time sec 3 + time nsec 274244959 + res sec 0 + rs nsec 1 \ No newline at end of file diff --git a/05_timers/userspace/main.c b/05_timers/userspace/main.c new file mode 100644 index 0000000..834b237 --- /dev/null +++ b/05_timers/userspace/main.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include + +void print_clock_details(clockid_t id, char *label) { + printf("Clock - %s\n", label); + struct timespec tp; + int result = 0; + result = clock_gettime(id, &tp); + if (result != 0) { + printf("Error clock_gettime: %s", strerror(errno)); + } + printf("\ttime sec %ld\n", tp.tv_sec); + printf("\ttime nsec %ld\n", tp.tv_nsec); + + result = clock_getres(id, &tp); + if (result != 0) { + printf("Error clock_getres: %s", strerror(errno)); + } + printf("\tres sec %ld\n", tp.tv_sec); + printf("\trs nsec %ld\n", tp.tv_nsec); +} + +// immitation of calculations, to show THREAD_CPUTIME and PROCESS_CPUTIME +void calculate() { + int i = 1; + while (i > 0) + { + i++; + } +} + +int main() { + calculate(); + + clockid_t clockid_array[] = { + CLOCK_REALTIME, + CLOCK_REALTIME_ALARM, + CLOCK_REALTIME_COARSE, + CLOCK_TAI, + CLOCK_MONOTONIC, + CLOCK_MONOTONIC_COARSE, + CLOCK_MONOTONIC_RAW, + CLOCK_BOOTTIME, + CLOCK_BOOTTIME_ALARM, + CLOCK_PROCESS_CPUTIME_ID, + CLOCK_THREAD_CPUTIME_ID + }; + char* clockid_labels_array[] = { + "CLOCK_REALTIME", + "CLOCK_REALTIME_ALARM", + "CLOCK_REALTIME_COARSE", + "CLOCK_TAI", + "CLOCK_MONOTONIC", + "CLOCK_MONOTONIC_COARSE", + "CLOCK_MONOTONIC_RAW", + "CLOCK_BOOTTIME", + "CLOCK_BOOTTIME_ALARM", + "CLOCK_PROCESS_CPUTIME_ID", + "CLOCK_THREAD_CPUTIME_ID" + }; + + int size = sizeof clockid_array / sizeof clockid_array[0]; + for (int i = 0; i < size; i++) { + print_clock_details(clockid_array[i], clockid_labels_array[i]); + } + + return 0; +} \ No newline at end of file diff --git a/05_timers/userspace/run.sh b/05_timers/userspace/run.sh new file mode 100755 index 0000000..dd40724 --- /dev/null +++ b/05_timers/userspace/run.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +rm a.out +gcc main.c +./a.out \ No newline at end of file diff --git a/06_memory/README.md b/06_memory/README.md new file mode 100644 index 0000000..4c22613 --- /dev/null +++ b/06_memory/README.md @@ -0,0 +1,22 @@ +# Memory management + +## Homework +1. Create user-space C or C++ program which tries to allocate buffers + with sizes 2^x for x in range from 0 to maximium possible value + using functions: + **malloc, calloc, alloca, (optional for C++) new **. + Measure time of each allocation/freeing. + 2^x means x power of 2 in this task. +Pull request should contains program source code and program output +in text format. + +2. Create kernel module and test allocation/freeing time for functions: + **kmalloc, kzmalloc, vmalloc, get_free_pages, + (optional and only for drivers integrated to kernel)alloc_bootmem**. + Measure the time of each allocation/freeing except alloc_bootmem. + The results should be presented in text file table with followed columns: + Buffer size, allocation time, freeing time. + Size unit is 1 byte, time unit is 1 ns. + +Pull request should contains source code of developed driver, Makefile +and program output from system log in text format. diff --git a/logs.txt b/logs.txt new file mode 100644 index 0000000..b1a8e0d --- /dev/null +++ b/logs.txt @@ -0,0 +1,42 @@ +# insmod /home/user/hello.ko +# cd MyObject/ +# echo "qwety1" > list +# echo "qwety2" > list +# echo "qwety3" > list +# cat list +qwety3 +qwety2 +qwety1 +# dmesg +hello: ---< list_show +hello: ---> hello_exit +hello: Clean node: qwety3 +hello: Clean node: qwety2 +hello: Clean node: q1 +hello: List_empty: 1 +hello: ---< hello_exit +hello: ---> hello_init +hello: ---< hello_init +hello: ---> list_store size_t: 7 +hello: value created: 7 +hello: ---> add_node +hello: ---< add_node +hello: ---< list_store +hello: ---> list_store size_t: 7 +hello: value created: 7 +hello: ---> add_node +hello: ---< add_node +hello: ---< list_store +hello: ---> list_store size_t: 7 +hello: value created: 7 +hello: ---> add_node +hello: ---< add_node +hello: ---< list_store +hello: ---> list_show +hello: Node copy to buf: qwety3 +hello: Node copy to buf: qwety2 +hello: Node copy to buf: qwety1 +# pwd +/sys/kernel/MyObject +# +