Linux Kernel II. Hello kernel - jak napisać pierwszy moduł

Podobne dokumenty
Laboratorium 1: Moduły jądra systemu Linux (jedne zajęcia) dr inż. Arkadiusz Chrobot

K. Konopko; Toolchain. Jądro Linuksa. dr inż. Krzysztof Konopko

Tworzenie oprogramowania

Wstęp do Informatyki i Programowania Laboratorium: Lista 0 Środowisko programowania

Programowanie I. O czym będziemy mówili. Plan wykładu nieco dokładniej. Plan wykładu z lotu ptaka. Podstawy programowania w językach. Uwaga!

Fragment wykładu z języka C ( )

Linux Kernel III. Character devices

Wst p do moduªów. Marcin Milewski. Wrocªaw, 28 pa¹dziernika Instytut Informatyki Uniwersytetu Wrocªawskiego

Laboratorium 1 Temat: Przygotowanie środowiska programistycznego. Poznanie edytora. Kompilacja i uruchomienie prostych programów przykładowych.

Programowanie Proceduralne

Kernel Kompilacja jądra

Kompilacja i scalanie programów w linii poleceń gcc i make

Część XVII C++ Funkcje. Funkcja bezargumentowa Najprostszym przypadkiem funkcji jest jej wersja bezargumentowa. Spójrzmy na przykład.

PROE wykład 3 klasa string, przeciążanie funkcji, operatory. dr inż. Jacek Naruniec

Programowanie obiektowe zastosowanie języka Java SE

Prosty sterownik. Michał mina86 Nazarewicz. 6marca

Programowanie obiektowe. Literatura: Autor: dr inŝ. Zofia Kruczkiewicz

1. Pierwszy program. Kompilator ignoruje komentarze; zadaniem komentarza jest bowiem wyjaśnienie programu człowiekowi.

Podstawy programowania. Wykład 9 Preprocesor i modularna struktura programów. Krzysztof Banaś Podstawy programowania 1

Co to jest NODE.JS? Nowoczesne środowisko programistyczne

Linux Kernel. Wprowadzenie

Wstęp do programowania INP003203L rok akademicki 2018/19 semestr zimowy. Laboratorium 3. Karol Tarnowski A-1 p.

Wprowadzenie do biblioteki klas C++

Programowanie w C++ Wykład 10. Katarzyna Grzelak. 21 maja K.Grzelak (Wykład 10) Programowanie w C++ 1 / 21

Make jest programem komputerowym automatyzującym proces kompilacji programów, na które składa się wiele zależnych od siebie plików.

Java jako język programowania

Programowanie niskopoziomowe

Programowanie obiektowe

RPC. Zdalne wywoływanie procedur (ang. Remote Procedure Calls )

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 8. Karol Tarnowski A-1 p.

Konfiguracja i kompilacja jądra Linux. Based on Free Electrons

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 15 kwietnia K.Grzelak (Wykład 8) Programowanie w C++ 1 / 33

Laboratorium Informatyka (I) AiR Ćwiczenia z debugowania

Katedra Elektrotechniki Teoretycznej i Informatyki. wykład 12 - sem.iii. M. Czyżak

PARADYGMATY PROGRAMOWANIA Wykład 4

Programowanie Strukturalne i Obiektowe Słownik podstawowych pojęć 1 z 5 Opracował Jan T. Biernat

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main.

Wstęp do Programowania, laboratorium 02

1 Zapoznanie się ze środowiskiem Xenomai.

WPROWADZENIE DO INFORMATYKI

IdyllaOS. Prosty, alternatywny system operacyjny. Autor: Grzegorz Gliński. Kontakt:

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Java Podstawy. Michał Bereta

Zaawansowane programowanie w języku C++ Funkcje uogólnione - wzorce

Linux Kernel. Michał Kulling.

Tworzenie oprogramowania

Programowanie w języku C++

Programowanie w C++ Wykład 7. Katarzyna Grzelak. 23 kwietnia K.Grzelak (Wykład 7) Programowanie w C++ 1 / 40

Podstawy Programowania.

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 1

Język JAVA podstawy. wykład 1, część 2. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

MentorGraphics ModelSim

Programowanie w C++ Wykład 9. Katarzyna Grzelak. 14 maja K.Grzelak (Wykład 9) Programowanie w C++ 1 / 30

Programowanie w C++ Wykład 6. Katarzyna Grzelak. 1 kwietnia K.Grzelak (Wykład 6) Programowanie w C++ 1 / 43

Podstawy wykorzystania bibliotek DLL w skryptach oprogramowania InTouch

Utworzenie pliku. Dowiesz się:

Wstęp do programowania

SYSTEMY OPERACYJNE I laboratorium 3 (Informatyka stacjonarne 2 rok, semestr zimowy)

Podstawy Informatyki Wprowadzenie do języka C dr inż. Jarosław Bułat

Wstęp do programowania INP003203L rok akademicki 2016/17 semestr zimowy. Laboratorium 1. Karol Tarnowski A-1 p.

Programowanie I C / C++ laboratorium 01 Organizacja zajęć

Wyrażenie include(sciezka_do_pliku) pozwala na załadowanie (wnętrza) pliku do skryptu php. Plik ten może zawierać wszystko, co może się znaleźć w

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej.

Programy użytkowe (utilities)

Warsztaty AVR. Instalacja i konfiguracja środowiska Eclipse dla mikrokontrolerów AVR. Dariusz Wika

Podstawy Programowania

Obsługa plików. Systemy Operacyjne 2 laboratorium. Mateusz Hołenko. 25 września 2011

Co nie powinno być umieszczane w plikach nagłówkowych:

SYSTEMY OPERACYJNE: STRUKTURY I FUNKCJE (opracowano na podstawie skryptu PP: Królikowski Z., Sajkowski M. 1992: Użytkowanie systemu operacyjnego UNIX)

Język JAVA podstawy. wykład 2, część 2. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

WPROWADZENIE DO JĘZYKA JAVA

WYKORZYSTANIE JĘZYKA GROOVY W TESTACH JEDNOSTKOWYCH, INTEGRACYJNYCH I AUTOMATYCZNYCH. Mirosław Gołda, Programista Java

Szablony klas, zastosowanie szablonów w programach

Automatyzacja kompilacji. Automatyzacja kompilacji 1/28

Jak napisać program obliczający pola powierzchni różnych figur płaskich?

Podstawy użytkowania Linux a

Konstruktory. Streszczenie Celem wykładu jest zaprezentowanie konstruktorów w Javie, syntaktyki oraz zalet ich stosowania. Czas wykładu 45 minut.

Praktyka programowania projekt

Programowanie Systemów Wbudowanych

MATERIAŁY DO ZAJĘĆ I. Podstawowe pojęcia. Algorytm. Spis treści Przepis

Architektury Usług Internetowych. Laboratorium 2. Usługi sieciowe

Wykład 1. Program przedmiotu. Programowanie Obiektowe (język C++) Literatura. Program przedmiotu c.d.:

Procesy pojęcia podstawowe. 1.1 Jak kod źródłowy przekształca się w proces

Generated by Foxit PDF Creator Foxit Software For evaluation only. System Szablonów

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Instrukcja laboratoryjna cz.3

ĆWICZENIE NR 4 KONFIGURACJA JĄDRA, USŁUGI SIECIOWE. KATEDRA ELEKTRONIKI POLITECHNIKA LUBELSKA

Automatyzacja kompilacji. Automatyzacja kompilacji 1/40

Programowanie mikrokontrolerów AVR

Podstawy języka skryptowego Lua

Wprowadzenie 5 Rozdział 1. Lokalna sieć komputerowa 7

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6

Programowanie Niskopoziomowe

Globalne / Lokalne. Wykład 15. Podstawy programowania (język C) Zmienne globalne / lokalne (1) Zmienne globalne / lokalne (2)

Tablice, funkcje - wprowadzenie

Wykład. Materiały bazują częściowo na slajdach Marata Dukhana

Cwiczenie nr 1 Pierwszy program w języku C na mikrokontroler AVR

Wstęp. Ale po co? Implementacja

Wykład VII. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

Transkrypt:

Linux Kernel II Hello kernel - jak napisać pierwszy moduł

Przypomnienie (I) Moduły uruchamiane są i działają w przestrzeni Kernela (Kernel space), Moduły piszemy w języku C, Moduły działają inaczej niż aplikacje: służą rozszerzaniu podstawowych funkcjonalności jądra systemu Linux, Popełnianie błędów programistycznych może owocować poważniejszymi problemami. page 2

Przypomnienie (II) Przykładowy i uproszczony schemat architektury aplikacji: Hardware Driver Kernel Syscall Library App page 3

Wywołania systemowe (syscalls) Podstawowe instrukcje systemu Linux dostępne z poziomu użytkownika, Zwykle obudowane bibliotekami systemowymi, nie są wywoływane wprost, Każda funkcja standardowych bibliotek języka C może być zastąpiona wywołaniem, bądź serią wywołań systemowych, Przykładowo: int printf(const char *format,...); [std C lib function] ssize_t write(int fd, const void *buf, size_t count); [syscall] page 4

Czy moduły możemy pisać w C++? (pytanie z poprzedniego wykładu) Najprostsza odpowiedź: NIE! Dlaczego? Bo... Kernel nie zapewnia wzparcia dla C++, Bo... nie ma innych sterowników w C++, Bo C jest wystarczające, aby napisać każdy sterownik. Trudniejsza odpowiedź: TAK! Zawsze możemy przepisać Kernel w języku C++ ;) Więcej informacji: http://www.tux.org/lkml/#s15-3 page 5

Cykl życia modułu Wczytaj moduł (Insert) Wywołaj funkcję inicjującą (Init function) komenda insmod Komenda rmmod Czekaj na polecenie (request) Kolejka poleceń (request queue) Remove module Wywołaj funkcję czyszczącą (Cleanup) page 6

Pierwszy moduł: przygotowanie (I) Czego potrzebujemy? Kompilatora GCC, który musi być odowiedni dla posiadanej wersji Linuxa, zwykle jest on dostarczany wraz z toolchainem, Skompilowanego, bądź odpowiednio przygotowanego kodu źródłowego systemu Linux, Konfiguracji Kernela (plik.config), Listy symboli używanych w Kernelu (plik Module.symvers). page 7

Pierwszy moduł: przygotowanie (II) Jeśli posiadamy skompilowane źródła systemu Linux w odpowiedniej wersji, to właśnie zaoszczędziliśmy sobie nieco pracy, Jeśli posiadamy prekompilowany system Linux (np. Arch Linux, Ubuntu czy Raspbian), to: Używamy przeglądarki Google, aby wyszukać instrukcję odtworzenia źródeł systemu Linux, Wszystkie instrukcje są do siebie podobne i sprowadzają się do pozyskania plików.config oraz Module.symvers, Większość popularnych systemów posiada łatwo dostępną instrukcję. page 8

Przykład: przygotowanie systemu Raspbian (III) Przykładowa instrukcja: https://github.com/notro/rpi-source/wiki Powyższa instrukcja w skrócie: Aktualizujemy kompilator GCC, jeśli jest taka potrzeba, Pobieramy skrypt i uruchamiamy go, a wtedy: Skrypt aktualizuje firmware RPI (także Kernel), pobiera źródła systemu Linux w najnowszej wersji do katalogu domowego, Odzyskuje konfigurację systemu Linux z /proc/config.gz, bądź generuje domyślną: make bcmrpi_defconfig, Pobiera plik Module.symvers (!), Wykonuje make modules_prepare. page 9

Plik.config W pliku.config przechowywane są informacje o obecnej konfiguracji systemu Linux, Aby skonfigurować Kernel użyj: make <configuration> [ls -l arch/arm/configs] make mrproper make menuconfig make oldconfig page 10

Plik Module.symvers przechowuje dane o eksportowanych przez Kernel symboli, Symbole to funkcje widoczne dla innych modułów, Budowa pliku: 0x5d9a4bf2 CRC, ipv6_chk_custom_prefix nazwa funkcji (symbol) net/ipv6/ipv6 moduł w którym symbol jest umiejscowiony. page 11

#include <linux/init.h> #include <linux/module.h> #include <linux/sched.h> MODULE_LICENSE("Dual BSD/GPL"); static int init hello_init(void) { printk(kern_alert "Hello kernel with process=%s (PID=%i, parent= %s)\n", current->comm, current->pid, current->parent->comm); return 0; } static void exit hello_exit(void) { printk(kern_alert "Goodbye kernel world.\n"); } module_init(hello_init); module_exit(hello_exit); Moduł Hello Kernel page 12

Pliki nagłówkowe Linux/module.h Plik potrzebny wszystkim dynamicznie ładowanym modułom, Zawiera wiele definicji między innymi makra MODULE_LICENSE, Linux/init.h Plik nagłówkowy zawierający definicje potrzebne to inicjalizacji modułów, m.in. makra module_init, module_exit, init, exit, Linux/sched.h Plik nagłówkowy zawierający m.in. definicje dostarczające dane o obecnym procesie, Current comm, current parent, current pid. page 13

Makro MODULE_LICENSE Możliwe licencje znaleźć można w pliku nagłówkowym linux/module.h, Dostępne licencje: GPL, GPL v2, Dual BSD/GPL, Dual MPL/GPL, Proprietary i inne..., Niektórych funkcji można używać jedynie w modułach oznaczonych konkretnymi licencjami, Moduły nie zawierające definicji licencji traktowane są jako proprietary, Kiedy moduł oznaczony jest jako proprietary, Kernel staje się skażony (ang. tainted ), Skażone Kernele nie są wspierane przez brać linuxową... page 14

Funkcja init static int init hello_init(void) { printk(kern_alert "Hello kernel with process=%s (PID=%i, parent= %s)\n", current->comm, current->pid, current->parent->comm); return 0; } Hello_init: funkcja statyczna, zwracająca wartość decymalną (integer), nie przyjmująca argumentów, init: znacznik mówiący Kernelowi, że funkcja jest używana tylko podczas inicjalizacji modułu (potem jest usuwana z pamięci), Printk: funkcja pisząca, podobna do funkcji printf w przestrzeni użytkownika (userspace), KERN_ALERT: poziom logowania, jest to zwykły string, current : struktura zawierająca informacje o obecnym procesie. page 15

Funkcja exit static void exit hello_exit(void) { printk(kern_alert "Goodbye kernel world.\n"); } Hello_exit: funkcja statyczna, nie zwracająca oraz nie przyjmująca wartości, exit: znacznik mówiący Kernelowi, że funkcja jest używana jedynie podczas kończenia pracy modułu, Jeśli funkcja oznaczona jako exit zostanie użyta w innym kontakście, zwrócony zostanie błąd. page 16

module_init(hello_init); module_exit(hello_exit); Makra module_init i module_exit Nazwy funkcji użyte jako argumenty makr module_init i module_exit są uruchamiane odpowiednio: W czasie inicjalizacji pracy modułu użyta zostanie funkcja hello_init, W czasie kończenia pracy modułu użyta zostanie funkcja hello_exit, Przykładowy wynik końcowy: page 17

KERN_VER := $(shell uname -r) PWD := $(shell pwd) KERNELDIR?= /lib/modules/$(kern_ver)/build obj-m := hello.o all: clean compile Kompilacja modułu: plik makefile compile: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean: $(MAKE) -C $(KERNELDIR) M=$(PWD) clean page 18

Dlaczego pliki makefile modułów Kernela wyglądają inaczej niż tradycyjne? Ponieważ plik makefile kompilowanego modułu staje się częścią procesu kompilowania całego Kernela, Ta linijka jest odpowiedzialna za dołączenie świeżo napisanego modułu do procesu kompilacji Kernela: obj-m := hello.o Kompilacja modułu: wyjaśnienie Za wywołanie procesu kompilacji odpowiada komenda $(MAKE): $(MAKE) -C $(KERNELDIR) M=$(PWD) modules page 19

Kompilacja modułu: informacje dodatkowe (I) Moduły możemy budować na dwa sposoby: Jako wbudowane (build-in), ładowane automatycznie podczas startu systeu Linux, Jako zewnętrzne (loadable), ładowane przed użytkownika za pomocą komendy insmod bądź modprobe, Aby zbudować moduł jako wbudowany należy w pliku.config : Oznaczyć moduł jako y, np. CONFIG_HELLO_WORLD=y Aby zbudować moduł jako zewnętrzny należy w pliku.config : Oznaczyć moduł jako m, np. CONFIG_HELLO_WORLD=m Dlatego też, jeśli w pliku makefile napiszemy: Obj-y := hello.o, nasz moduł będzie wbudowany, Obj-m := hello.o, nasz moduł będzie zewnętrzyny. page 20

Kompilacja modułu: informacje dodatkowe (II) Budowanie modułu złożonego z plików hello1.c and hello2.c: obj-m := hello.o hello-objs := hello1.o hello2.o Nietypowa komenda $(MAKE) : $(MAKE) -C $(KERNELDIR) M=$(PWD) modules Odpowiada ona za wywołanie dodatkowego procesu budowania dziecka w obrębie nadrzędnego polecenia make. page 21

Dynamiczne uruchamianie i kończenie pracy modułów insmod aby wczytać I uruchomić moduł, rmmod aby zakończyć pracę modułu, lsmod aby wyświetlić załadowane moduły, Polecenie: dmesg tail wyświetli wszystkie polecenia printk użyte w module. page 22

Kernel symbol table Kernel Symbol Table to po prostu Tablica Symboli Kernela, Tablica symboli odnosi się bezpośrednio to wspomnianego wczesniej pliku Module.symvers, Co należy zrobić, aby napisaną przez nas funkcję dodać do tablicy symboli Kernela? Należy wyeksportować ją za pomocą makra: EXPORT_SYMBOL(), Po użyciu makra EXPORT_SYMBOL Kernel umieści naszą funkcję w globalnej tablicy symboli i stanie się ona widoczna dla wszystkich modułów w Kernelu. page 23

Potencjalne problemy i pozbywanie się ich (I) Kiedy zobaczymy taki błąd: Error inserting './hello.ko': -1 Invalid module format Znaczy to, że coś poszło nie tak... Aby przyjrzeć się bliżej problemowi wpisujemy: cat /var/log/messages, bądź dmesg i sprawdzamy ostatnie wpisy, Najczęstsze błędy: 1. hello: version magic '<this>' should be '<that>' Zła wersja kernela: należy poszukać DOKŁADNIE takiego samego Kernela, bądź pogrzebać w /linux/module.h (czasem trudne). page 24

Potencjalne problemy i pozbywanie się ich (II) 2. hello: no symbol version for module_layout Źródła systemu Linux nie są kompletne. Brakuje w nich pliku Module.symvers : należy pobrać plik od twórcy, bądź skompilować źródła systemu Linux, które posiadamy. 3. W przypadku każdego problemu najprostszym, rozwiązaniem jest przeszukanie internetu. Kernel posiada znakomitą dokumentację! :) page 25

Aby skompilować swój moduł potrzebujesz odpowiednio przygotowane źródła systemu Linux: konfiguracja oraz stworzenie tablicy symboli są niezbędne! Moduły możemy budować jako integralną część Linuxa (build-in) bądź jako zewnętrzne pliki ładowane dynamicznie (loadable), Proces budowania modułu jest częścią systemu budowania CAŁEGO systemu Linux, Pliki nagłówkowe systemu Linux dostarczają wielu ciekawych informacji, Częste sięganie do dokumentacji systemu Linux może zaoszczędzić wielu nerwów, Programowanie w systemie Linux wymaga wprawy i szczególnie na początku, może sprawiać problem. Podsumowanie page 26

Linux Kernel Wprowadzenie Koniec