Table of Contents
- Przygotowanie środowiska pracy
- Moduły jądra – informacje ogólne
- Zarządzanie modułami
- Przykład 1 - Tworzenie prostego sterownika
- Dodanie parametrów do modułu
- Obsługa urządzeń znakowych
- Przykład 2 - urządzenie znakowe
- Zadania
- Dodatkowa lektura
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
- Przygotowanie środowiska pracy
- Moduły jądra – informacje ogólne
- Zarządzanie modułami
- Skrócona lista komend
- Lista załadowanych modułów
- Załadowanie modułu
- Usunięcie załadowanego modułu
- Przykład 1 - Tworzenie prostego sterownika
- Dodanie parametrów do modułu
- Obsługa urządzeń znakowych
- Przykład 2 - urządzenie znakowe
- Opis kodu
- Zadania
- Zadania do wykonania na zajęciach
- Zadanie domowe
- Dodatkowa lektura
Przygotowanie środowiska pracy
Uwaga: Systemy Linux przygotowane na potrzeby laboratoriów z przedmiotu Systemy Operacyjne nie są w rzeczywistości całkowicie odseparowanymi maszynami. Mają one współdzielone jądro i nie ma możliwości ładowania własnych modułów do jądra. Z tego powodu wymagane jest przy wykonywaniu ćwiczeń pobranie odpowiednich obrazów systemu i uruchomienie wirtualnej maszyny za pomocą np. qemu.
Pobranie obrazu na dysk lokalny. W tym celu proszę wykonać następujące komendy:
mkdir -p /tmp/sop_images && cp /media/$(whoami)/resources/Wawrzyniak\ Wojciech/debian_sop.img /tmp/sop_images
Uruchomienie obrazu:
cd /tmp/sop_images
qemu-system-x86_64 -hda debian_sop.img -redir tcp:2222::22 -m 1024M -smp 1
Teraz można już się podłączyć do maszyny z innej konsoli poprzez ssh (lokalnie z linuksa na którym została właśnie uruchomiona wirtualna maszyna z obrazem systemu Linux):
ssh -p 2222 sop@localhost
Dane do logowania:
- login:
sop
- hasło:
sop2017
lub
- login:
root
- hasło:
sop2017
Moduły jądra – informacje ogólne
Przez dziesięciolecia sterowniki urządzeń systemu UNIX były statycznie łączone z jądrem, dzięk czemu były dostępne W pamięci po każdym uruchomieniu systemu. W środowisku, w którym rozwijały się ówczesne wersje Uniksa, kiedy minikomputery i wydajne stacje robocze zawierały stosunkowo niewielkie i stale zbiory urządzeń wejścia-wyjścia, wspomniany model sprawdzał się całkiem dobrze. Wystarczyło skompilować jądro ze sterownikami dla odpowiednich urządzeń wejścia-wyjścia. Jeśli rok później dana organizacja decydowała się na zakup nowego dysku, można było po prostu raz jeszcze skompilować jądro. Dla nikogo nie był to poważny problem.
Po wprowadzeniu systemu Linux dla platformy PC nagle wszystko uległo zmianie. Liczba urządzeń wejścia-wyjścia dostępnych dla komputerów PC o kilka rzędów wielkości przekraczała liczbę tego rodzaju urządzeń instalowanych w minikomputerach. Co więcej, mimo że większość użytkowników Linuksa dysponuje (lub może łatwo uzyskać) kompletny kod źródłowy tego systemu, prawdopodobnie dla niemal wszystkich operacja dodania nowego sterownika, aktualizacji wszystkich struktur danych opisujących sterowniki urządzeń, ponowna kompilacja jądra i instalacja go w formie uruchamialnego systemu (nie wspominając o rozwiązywaniu problemów związanych z usuwaniem usterek w razie problemów z rozruchem jądra) byłaby kłopotliwa.
W systemie Linux rozwiązano ten problem — wprowadzono tzw. ładowalne moduły (ang. loadable modules). To fragmenty kodu, które można ładować do jądra systemu operacyjnego już w czasie jego działania. Do najbardziej popularnych modułów tego typu należą sterowniki urządzeń znakowych i blokowych, jednak równie dobrze można instalować w ten sposób całe systemy plików, protokoły sieciowe, narzędzia monitorujące wydajność i dowolne inne mechanizmy.
W trakcie ładowania modułu należy wykonać szereg operacji. Po pierwsze moduł musi zostać przeniesiony do pamięci W trakcie ładowania. Po drugie system musi sprawdzić, czy zasoby wymagane przez dany sterownik (np. poziomy żądań przerwań) są dostępne, i — jeśli tak — oznaczyć je jako wykorzystywane. Po trzecie należy ustawić wszelkie niezbędne wektory przerwań. Po czwarte systemu musi zaktualizować tablicę sterowników, aby obsługiwała nowy typ urządzeń. Dopiero po wykonaniu tych kroków sterownik może przystąpić do inicjalizacji swojego urządzenia. Sterownik zostaje wówczas w pełni zainstalowany i dysponuje takimi samymi prawami jak sterowniki instalowane statycznie. Ładowalne moduły są obecnie obsługiwane także przez inne współczesne systemy UNIX.
Tanenbaum, A., & Bos, H. (2016). Moduły w systemie Linux. W Systemy operacyjne (pp. 776-777, wyd. 4). Helion.
W systemie Linux sterowniki urządzeń mogą być umieszczone:
- wewnątrz jądra (np. te które są niezbędne do uruchomienia)
- wydzielone w postaci osobnych modułów.
Zauważmy, że z uwagi na dużą liczbę dostępnych urządzeń wkompilowywanie wielu sterowników w jądro systemu Linux byłoby bardzo kłopotliwe. Dlatego wprowadzono tzw. ładowalne moduły (ang. loadable modules). Są to fragmenty kodu, które można załadować do jądra systemu już w trakcie jego działania.
Do najpopularniejszych typów takich modułów należą:
- sterowniki urządzeń znakowych
- sterowniki urządzeń blokowych (np. dyski).
Jednak w ten sposób mogą być tworzone również całe systemy plików, protokoły sieciowe, i wiele wiele innych.
Zarządzanie modułami
Skrócona lista komend
lsmod
- wylistowanie zaladowanych modułów jądramodprobe
- pozwala dodać i usunąć moduły jądra z katalogu/lib/modules/$(uname -r)
. Dodatkowo pozwala załadować wszystkie moduły potrzebne do działania naszego modułuinsmod <nazwa_plik.ko>
- ładuje moduł jądra o nazwie podanej jako parametr (ładowanie możliwe z lokalnego katalogu)rmmod <nazwa modulu>
- usuwa moduł jądra.
Lista załadowanych modułów
Większość "sterowników" urządzeń jest albo wkompilowana w jądro systemu (choćby te, które są niezbędne do uruchomienia), albo jako moduły ładowane dynamicznie, gdy dane urządzenie zostanie wykryte. Aby zobaczyć jakie moduły zostały załadowane wystarczy użyć polecenia lsmod
(większość linii została wycięta, lista jest zwykle dłuższa).
$ lsmod
Module Size Used by
xt_mac 16384 1
xt_tcpudp 16384 1
dccp_diag 16384 0
snd_pcm 106496 0
snd_timer 32768 1 snd_pcm
snd 86016 2 snd_timer,snd_pcm
soundcore 16384 1 snd
Z powyższego możemy odczytać: nazwę modułu, zajmowaną przez niego pamięć oraz jakie inne moduły są od niego zależne (np. snd jest używany przez snd_timer).
Załadowanie modułu
Aby załadować moduł wraz z zależnościami możemy wykorzystać polecenie
modprobe nazwa_modułu
. Jednak ważne by moduł był zainstalowany w odpowiednim katalogu (w naszym przypadku w /lib/modules/4.9.0-4-amd64
).
Przykładowa komenda ładująca moduł jądra.
$ modprobe arc4
Moduł jądra można również załadować za pmocą polecenia insmod
. Np.:
insmod hello.ko
Jednak w tym przypadku plik hello.ko
może znajdować się w bieżącym katalogu
Usunięcie załadowanego modułu
$ rmmod nazwa_modułu.
Usunięcie nie powiedzie się, jeżeli moduł jest używany.
Przykład 1 - Tworzenie prostego sterownika
W celu utworzenia prostego sterownika należy przygotować dwa pliki: Makefile oraz plik źródłowy.
Ponadto ważne jest by w systemie był zainstalowany pakiet linux-headers-$(uname -r)
. Gdzie polecenie uname -r
pozwala pobrać aktualny numer wersji jądra systemu. Ważne jest by posiadane pliki nagłówkowe były zgodne co do wersji aktualnym jądrem systemu.
Makefile:
obj-m += hello.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
plik hello.c:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
MODULE_AUTHOR("Systemy operacyjne 2017 UAM");
MODULE_DESCRIPTION("Prosty modul Hello World From Module");
static int __init hello_init(void)
{
printk(KERN_INFO "Hello world z modulu Hello!\n");
return 0; // Wartosc rozna od 0 zwraca blad
}
static void __exit hello_cleanup(void)
{
printk(KERN_INFO "Cleanup z moduly Hello!.\n");
}
module_init(hello_init);
module_exit(hello_cleanup);
Opis kodu:
- Załączone pliki nagłówkowe
linux/module.h
,linux/kernel.h
,linux/init.h
są konieczne podczas kompiliacji każdego z modułów jądra - Funkcja
hello_init
zostanie wywołana podczas dogrywania modułu do jądra (np. poleceniemmodproble hello
). Zwraca ona wartość typuint
i powinna być ona 0 jeżeli moduł został załadowany poprawnie. - Funkcja
hello_cleanup
zostanie wywołana podczas usuwania modułu z jądra. Zadaniem jej jest "posprzątanie" po tym co wcześniej zostało wykonane w module np. w funkcji "hello_init". - Linie
module_init(hello_init)
i analogicznamodule_exit(hello_cleanup)
służą do powiadomienia systemu od których funkcji powinno rozpocząć/zakończyć się działanie modułu.
Stałe uprawnień dla plików:
- S_IRWXU - read, write, execute/search by owner
- S_IRUSR - read permission, owner
- S_IWUSR - write permission, owner
- S_IXUSR - execute/search permission, owner
- S_IRWXG - read, write, execute/search by group
- S_IRGRP - read permission, group
- S_IWGRP - write permission, group
- S_IXGRP - execute/search permission, group
- S_IRWXO - read, write, execute/search by others
- S_IROTH - read permission, others
- S_IWOTH - write permission, others
- S_IXOTH - execute/search permission, others
- S_ISUID - set-user-ID on execution
- S_ISGID - set-group-ID on execution
- S_ISVTX - on directories, restricted deletion flag
Dodanie parametrów do modułu
Moduły jądra często muszą być dodatkowo konfigurowane. Istnieje możliwość ustawienia dodatkowych parametrów podczas ładowania modułu (lub też podczas ich działania). Poniżej przedstawiono kod posiadający parametr o nazwie "parameter".
static char* parameter="Parametr dla hello_param module";
module_param(parameter, charp, S_IRUGO);
MODULE_PARM_DESC(parameter, "Napis zapisywany w logach");
Wyjaśnienie:
static char* parameter
- deklarowane zmienne muszą być globalnymi zmiennymi statycznymimodule_param(parameter, charp, S_IRUGO);
- każda zmienna musi być przetwarzana za pomocą makramodule_param()
. Pierwszy argument to nazwa parametru, drugi typ zmiennej, a trzeci oznacza uprawnienia do danego parametru. (S_IRUGO
- parametr może być czytany przez wszystkich ale nie może być zmieniany).
Istnieje możliwość wyświetlenia wartości zmiennych w logach systemu używając składni analogicznej jak w poleceniu printf
:
printk(KERN_INFO "Hello world z modulu Hello - parametr: %3s!\n", parameter);
Obsługa urządzeń znakowych
Podstawowym zadaniem modułu jest dostarczenie użytkownikowi pewnej funkcjonalności sprzętu. Do tego celu jest wymagana komunikacja użytkownika z modułem. Zapewnić to mogą specjalne pliki zwane plikami urządzeń
(ang. device files). Pliki te można znaleźć w katalogu /dev i podzielić je można na dwa typy:
- urządzenia znakowe (np. karty sieciowe}
- urządzenia blokowe (np. dyski itp.)
Za pomocą polecenia ls -l /dev
można wypisać listę wszystkich urządzeń. Urządzenia znakowe rozpoczynają się od "literki" "c", natomiast urządzenia blokowe od literki "b".
Przykład 2 - urządzenie znakowe
https://github.com/skuhl/sys-prog-examples/blob/master/kernel-module/chardev.c
Opis kodu
To jest dobre miejsce by wykonać zadanie 2 z ćwiczeń. Następnie jak zrozumiesz działanie zaprezentowanego modułu przejdź do zrozumienia kodu.
Inicjalizacja modułu
Podczas inicjalizacji modułu init_module()
wywołana zostaje funkcja rejestracji urządzenia.
/* This function is called when the module is loaded */
int init_module(void)
{
Major = register_chrdev(0, DEVICE_NAME, &fops);
if (Major < 0) {
printk(KERN_ALERT "Registering char device failed with %d\n", Major);
return Major;
}
printk(KERN_INFO "I was assigned major number %d. To talk to\n", Major);
printk(KERN_INFO "the driver, create a dev file with\n");
printk(KERN_INFO "'mknod /dev/%s c %d 0'.\n", DEVICE_NAME, Major);
printk(KERN_INFO "Try various minor numbers. Try to cat and echo to\n");
printk(KERN_INFO "the device file.\n");
printk(KERN_INFO "Remove the device file and module when done.\n");
return SUCCESS;
}
Podczas inicjalizacji następuje zarejestrowanie modułu do obsługi odpowiedniego urządzenia. W tym celu wykonywana jest funkcja register_chrdev(0, DEVICE_NAME, &fops);
.
Parametrami są kolejno:
- numer główny - na podstawie numeru głównego system rozróżnia który z modułów powinien obsługiwać operacje dotyczące urządzenia w systemie. W przypadku podania 0 system sam przydziela numer.
- nazwa urządzenia
- struktura opisująca jakie operacje na urządzeniu będą obsługiwane. W naszym przypadku moduł obsługuje 4 funkcje:
static struct file_operations fops = {
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release
};
Opis wykorzystania funkcji:
static int device_open(struct inode *, struct file *);
- wywoływana podczas otwarcia urządzenia do odczytu (open
)static int device_release(struct inode *, struct file *);
- wywoływana podczas zamknięcia pliku (close
)static ssize_t device_read(struct file *, char *, size_t, loff_t *);
- wywoływana podczas operacji czytania z pliku (read
)static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
- wywoływana podczas operacji zapisu do pliku (write
)
Otwarcie urządzenia
/*
* Called when a process tries to open the device file, like
* "cat /dev/mycharfile"
*/
static int device_open(struct inode *inode, struct file *file)
{
static int counter = 0;
if (Device_Open)
return -EBUSY;
Device_Open++;
sprintf(msg, "I already told you %d times Hello world!\n", counter++);
msg_Ptr = msg;
try_module_get(THIS_MODULE);
return SUCCESS;
}
W funkcji tej mamy zadeklarowaną zmienną statyczną counter
(przy każdym kolejnym wywołaniu jej wartość nie jest kasowana. I tak przy kolejnych wywołaniach zmienna counter wynosi 1,2,3,4, id.
Zmienna Device_Open
przechowuje ile razy urządzenie zostało otwarte (np. metodą open
). W naszym przypadku nie ma możliwości by urządzenie zostało otwarte więcej niż jeden raz. Wynika to ze sprawdzenie if (Device_Open) return -EBUSY
. Tak więc jeżeli wartość zmiennej jest większa od 0 to funkcja zwraca błąd (wartość -EBUSY
).
Następnie generowany jest odpowiedni napis I already ..... %d times ...
) i umieszczany w pamięci wskazywanej przez zmienną msg
.
Ponadto występuje tutaj wywołanie funkcji: try_module_get(THIS_MODULE)
- pozwala ona systemowi Linux zliczać liczbę aktywnie podłączonych procesów do modułu. Zapobiega to możliwości usunięcia używanego aktualnie modułu z jądra.
Zamknięcie urządzenia
/*
* Called when a process closes the device file.
*/
static int device_release(struct inode *inode, struct file *file)
{
Device_Open--; /* We're now ready for our next caller */
/*
* Decrement the usage count, or else once you opened the file, you'll
* never get get rid of the module.
*/
module_put(THIS_MODULE);
return 0;
}
W funkcji tej zmniejszamy o jeden liczbę otwartych urządzeń Device_Open--
.
Ponadto funkcja put_module(THIS_MODULE)
zmniejsza liczbę aktywnie podłączonych procesów do modułu przez system Linux.
Odczyt z urządzenia
/*
* Called when a process, which already opened the dev file, attempts to
* read from it.
*/
static ssize_t device_read(struct file *filp, /* see include/linux/fs.h */
char *buffer, /* buffer to fill with data */
size_t length, /* length of the buffer */
loff_t * offset)
{
/*
* Number of bytes actually written to the buffer
*/
int bytes_read = 0;
/*
* If we're at the end of the message,
* return 0 signifying end of file
*/
if (*msg_Ptr == 0)
return 0;
/*
* Actually put the data into the buffer
*/
while (length && *msg_Ptr) {
/*
* The buffer is in the user data segment, not the kernel
* segment so "*" assignment won't work. We have to use
* put_user which copies data from the kernel data segment to
* the user data segment.
*/
put_user(*(msg_Ptr++), buffer++);
length--;
bytes_read++;
}
/*
* Most read functions return the number of bytes put into the buffer
*/
return bytes_read;
}
Odczyt jest najbardziej skomplikowaną funkcją w naszym kodzie. Wynika to głównie z uwagi na różnice wynikające z działania kodu w trybie użytkownika i jądra. Przykładowymi funkcjami odróżniającymi tryb jądra od trybu użytkownika są:
- w trybie jądra możliwy jest dostęp do całej pamięci systemu
- tryb jądra nie obsługuje formatów zmiennoprzecinkowych
- adresy (wskaźniki) z trybu użytkownika nie są poprawne w trybie jądra (i odwrotnie). Dlatego należy używać specjalnych funkcji do kopiowania danych (w naszym przypadku używana jest funkcja
put_user()
.
Zadaniem funkcja device_read()
jest skopiowanie napisu ze zmiennej występującej w module msg
(tryb jądra) do bufora buffer
(tryb użytkownika). W tym celu wykonywane są następujące operacje:
- ustawienie liczby aktualnie odczytanych bajtów w tym wywołaniu fukncji
bytes_read
na0
. - sprawdzenie czy wskaźnik na aktualnie kopiowany bajt (
*msg_Ptr
) nie jest końcem napisu (znak ascii 0). - wykonanie pętli, a w każdej jej iteracji skopiowanie jednego znaku do bufora znajdującego się w pamięci użytkownika. W tym celu wykonywane jest polecenie
put_user(*(msg_Ptr++), buffer++)
, które kopiuje jeden znak spod adresu wskazywanego przezmsg_Ptr
do buforabuffer
.
Zauważmy że podczas kopiowania automatycznie inkrementowany jest adres msg_Ptr
oraz buffer
. W ten sposób w każdej kolejnej iteracji pętli wskaźniki te będą wskazywać kolejny znak w napisie msg_Ptr
oraz kolejne miejsce w buforze użytkownika gdzie ten znak powinien zostać skopiowany.
Na końcu funkcji następuje zwrócenie liczby odczytanych znaków.
Zapis do urządzenia
/*
* Called when a process writes to dev file: echo "hi" > /dev/hello
*/
static ssize_t
device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
{
printk(KERN_ALERT "Sorry, this operation isn't supported.\n");
return -EINVAL;
}
W naszym przypadku funkcja zwraca błąd. A implementacja tej funkcji jest zadaniem domowym.
Zadania
Zadania do wykonania na zajęciach
Zadanie 1
Utwórz w systemie katalog src_modules
w katalogu domowym użytkownika root
Następnie skompiluj kod z przykładu 1 poleceniem make
.
Załaduj moduł poleceniem
insmod ./hello.ko
Następnie sprawdź działanie napisanego sterownika za pomocą polecenia dmesg
.
Jako wynik powinna pojawić się podobny tekst:
[ 1934.076984] Hello world z modulu Hello!
Usuń moduł ze sterownika i ponownie sprawdź wynik operacji za pomocą polecenia lsmod
oraz dmesg | tail
Zadanie 2
Stwórz moduł sop_params
który:
- ma parametry:
char* name
z domyślną nazwąSOP_2017
. - ma parametr:
int number
z domyślną wartością równą 1. - Podczas ładowania modułu w logach systemu powinien pojawić się napis
"Pomyslnie zaladowano modul z parametrami: <name> <number>"
, gdzie w miejsca<name>
oraznumber
zostaną wstawione wartości zmiennych z modułu.
Załaduj moduł przekazując domyślne parametry. Następnie usuń go i załaduj poleceniem insmod sop_params.ko name=Imie number=indeks
.
Sprawdź wynik działania modułu w logach systemu.
Zadanie 3
Utwórz moduł jądra chardev
i załaduj go poleceniem insmod
.
Następnie:
- Sprawdź logi w poszukiwaniu potrzebnej informacji o utworzeniu pliku specjalnego w systemie w celu obsługi urządzenia.
- Odczytaj wiadomość z urządzenia (poleceniem
cat
). - Zapisz jakąś wiadomość w urządzeniu
/dev/chardev
i sprawdź komunikat w logach (dmesg
).
Zadanie domowe
Napisz modul lab_pamiec.c
, który implementuje urządzenie znakowe. Założenia modułu:
- Zapisywanie znaków do urządzenia znakowego powinno powodować zapamiętanie tekstu w buforze.
- Odczytanie z urządzenia (
/dev/module_pamiec
) powinno spowodować wczytanie wcześniej zapamiętanego tekstu. - Podczas załadowania modułu powinna być możliwość ustawienia domyślnej wielkości bufora (przy czym cały czas maksymalna długość to 100 znaków). I wartość ta powinna być zapisana w logach.
- Jeżeli zostanie zapisany do urządzenia tekst przekraczający długość bufora powinien być on zapamiętany i automatycznie przycinany do długości bufora.
- Utwórz plik log.txt zawierający ostatnie linie logów ukazujące poprawne działanie napisanego modułu z wykorzystaniem przekazanej długości bufora (np. 90).
Przykładowe działanie modułu
$ insmod lab_pamiec.ko
$ echo "ala ma kota" > /dev/lab_pamiec
$ cat /dev/lab_pamiec
ala ma kota
$ rmmod lab_pamiec
$ insmod lab_pamiec.ko length=5
$ echo "ala ma kota" > /dev/lab_pamiec
$ cat /dev/lab_pamiec
ala m
$ rmmod lab_pamiec
Uwaga: Należy zwrócić uwagę, że dostęp do pamięci z poziomu jądra różni się od dostępu do pamięci z poziomu użytkownika (zwykłego programu). Dlatego też podczas komunikacji (np. poleceniem cat /dev/lab_pamiec
) należy używać funkcji get_user
, put_user
, copy_from_user
, copy_to_user
. Jako wyjaśnienie spójrz na metodę device_read
w przykładowym module znakowym.
Do kopiowania bufora w metodzie device_write
przydatne mogą być następujące komendy:
get_user
copy_from_user
Punkty kontrolne rozwiązania
- poprawny ładowany kod źródłowy modułu wraz z plikiem Makefile
- obsługa zmiennej buffer_size oraz plik logów potwierdzających poprawne działanie modułu
- Napisanie metody
device_write
- Poprawne obsłużenie zapisu
device_write
nawet przy wielokrotnym wywołaniu metody zapisującej - np. wywołanie polecenia zapisu za pomocą komendy cat z tekstem zapisanym w kilku liniach:
$ insmod lab_pamiec.ko
$ cat > /dev/lab_pamiec
ala
ma
kota
$ cat /dev/lab_pamiec
ala
ma
kota
$ rmmod lab_pamiec
Wykonywanie zadania domowego
Proszę zwrócić uwagę, że zadanie domowe należy wykonać na przygotowanym obrazie systemu Linux (nie na maszynach na Proxmox!). Istnieje kilka sposobów wykonania zadania domowego:
- W salach komputerowych - Wykonanie zadania na komputerach w salach na Wydziale Matematyki i Informatyki
- qemu - Pobranie obrazu pliku
debian_sop.img
zcontact.dir - Wawrzyniak Wojciech
na swój komputer i uruchomienie systemu za pomocąqemu
(podobnie jak na zajęciach w salach komputerowych, jednak należy zmienić ścieżki do plikudebian_sop.img
w wywoływanej komendzie. - VirtualBox - Pobranie obrazu pliku
debian_sop.vdi
zcontact.dir - Wawrzyniak Wojciech
(/media/LOGIN-UŻYTKOWNIKA/resources/Wawrzyniak\ Wojciech
) i uruchomienie obrazu w programieVirtualBox
.
Uwaga: w ostatnim przypadku, mogą wystąpić problemu z dostępem do sieci w uruchomionym systemie. Wtedy należy:
- Ustawić jako sieć Mostkowana karta sieciowa (bridged)
- Po uruchomieniu systemu zalogować się w terminalu jako "root" i wpisać komendę
dhclient
Następnie odczytać numer IP:
ip show adds
I można już się łączyć przez ssh do maszyny wirtualnej (o odczytanym adresie IP np.
root@debian-sop:~# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:ad:b2:ff brd ff:ff:ff:ff:ff:ff
inet 192.168.1.40/24 brd 192.168.1.255 scope global enp0s3
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fead:b2ff/64 scope link
valid_lft forever preferred_lft forever
Czyli w powyższym przykładzie 192.168.1.40
.
W celu pobrania obrazu systemu np. z domu można podłączyć się przez protokół SFTP do serwera lts.wmi.amu.edu.pl. Obrazy plików debian_sop.img
, debian_sop.vdi
znajdują się w katalogu: /media/LOGIN-UŻYTKOWNIKA/resources/Wawrzyniak\ Wojciech
.