- Wprowadzenie
- Zadania do wykonania na zajęciach
- Konfiguracja nietypowych urządzeń
- Zadania domowe
- Materiały uzupełniające
- Przygotowanie do kolejnych zajęć
Wprowadzenie
W przypadku klasycznych systemów (desktop do pracy biurowej, prosty serwer WWW) istnieją gotowe rozwiązania, nie wymagające ręcznej konfiguracji, czy instalacji pakietów spoza domyślnie dostępnych. Model taki jest wystarczający dla większości instalacji. Czasami jednak potrzebny jest system, który będzie współpracował z nietypowym sprzętem lub zawierał oprogramowanie, które nie jest dostępne w formie pakietów (np. napisane specjalnie dla konkretnego systemu).
Zadania do wykonania na zajęciach
Konfiguracja nietypowych urządzeń
Zadanie 1
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).
Aby załadować moduł wraz z zależnościami możemy wykorzystać polecenie
modprobe nazwa_modułu
(np. arc4 -- nie zadziała to jednak na Proxmox!).
Aby usunąć moduł (także niemożliwe na Proxmoksie) wystarczy wpisać
rmmod nazwa_modułu
. Usunięcie nie powiedzie się, jeżeli moduł jest używany.
Konfiguracja modułów (np. domyślne opcje) znajduje się w pliku
/etc/modules
oraz w plikach znajdujących się w katalogu
/etc/modprobe.d
Sprawdź jakie moduły są załadowane w systemie na którym pracujesz.
Zadanie 2
Aby wykonać następne zadanie, należy zainstalować pakiety gcc
i make
:
sudo apt-get install gcc make lzip
Stwórzmy plik tekstowy o nazwie program.c z następującą zawartością.
#include <stdio.h>
int main(){
printf("Something\n");
return 0;
}
a następnie skompilujmy poleceniem:
gcc -Wall -ansi -o program program.c
(przełącznik -Wall
wyświetla wszystkie ostrzeżenia, a -ansi
sprawdza, czy program jest zgodny z ANSI C; opcja -o
pozwala podać
nazwę pliku wynikowego, domyśną nazwą jest a.out
).
Jeżeli kompilacja zakończyła się sukcesem (tzn. kompilator nie zgłosił błędów), to możemy wykonać nasz program
$ ./program
Something
Zadanie 3
Jako, że większość pakietów dostępnych wyłącznie w postaci źródeł (nie w pakietach) stanowią duże projekty (kompilacja
byłaby problemem na dostępnej platformie; zarówno ze względu na dostępną pamięć, jak i czas kompilacji), do demonstracji
wybieramy prosty edytor ed
(dostępny także w pakiecie, ale domyślnie niezainstalowany).
Na początku pobieramy kod ze strony, rozpakowujemy i przechodzimy do katalogu projektu
$ wget https://ftp.gnu.org/gnu/ed/ed-1.14.2.tar.lz
$ tar xavf ed-1.14.2.tar.lz
$ cd ed-1.14.2
$ ls
AUTHORS COPYING ChangeLog INSTALL Makefile.in NEWS README TODO buffer.c carg_parser.c carg_parser.h
configure doc ed.h global.c io.c main.c main_loop.c red.in regex.c signal.c testsuite
W pliku INSTALL
(czasami w README
) jest opisany proces instalacji. W tym przypadku należy wywołać skrypt configure
(dostępne
opcje po wywołaniu z parametrem --help
), make
(zbudowanie całości), make install
(w naszym przypadku sudo make install
,
bo do instalacji potrzebne są uprawnienia użytkownika root
).
$ ./configure
$ make
$ sudo make install
Uwaga: w przypadku systemów mających swój system pakietów instalacja programów zewnętrznych może powodować problemy i powinna być stosowana wyłącznie w przypadku, gdy nie ma innej możliwości.
Zadanie 4
Kolejnym etapem jest budowa własnego pakietu. Zamiast tworzyć skrypt generującego konfigurację (configure), stworzymy tylko
plik dla programu make. Domyślnie sprawdzane są nazwy GNUmakefile
, Makefile
, makefile
. W naszym przykładzie niech
się nazywa Makefile
, jest to najbardziej popularny wybór, a ze względu na domyślny porządek sortowania będzie jednym z pierwszych plików
wyświetlanych przez polecenie ls
, bo większość plików ma nazwy rozpoczynające się od małej litery.
Plik Makefile
w podstawowej wersji wygląda następująco:
cel: zależność1 zależność2
polecenie_do_zbudowania_celu
gdzie zależność może być innym celem lub plikiem. Uwaga: wcięcie w powyższym pliku to jeden znak tabulacji, a nie kilka spacji!
Konstrukcja taka gwarantuje, że podczas kolejnych wywołań programu make
ponownie zostaną przebudowane wyłącznie te cele,
których zależności się zmieniły. Dla programu z Zadania 2 plik mógłby wyglądać następująco:
program: program.c
gcc -Wall -ansi -o program program.c
Wywołanie programu make zbuduje program tylko wtedy, gdy czas utworzenia/zmiany pliku program.c
jest późniejszy niż
wynikowego pliku program
$ make
gcc -Wall -ansi -o program program.c
$ make
make: 'program' is up to date.
Zauważmy, że polecenie touch program.c
zaktualizuje datę dostępu do pliku, przez co make
przekompiluje program.
Zadanie 5
Funkcjonalności (np. zapis pliku na dysk, przeskalowanie okienka) powtarzają się w wielu programach. Aby nie pisać ich dla każdego projektu od początku, stworzone zostały tzw. biblioteki. W przypadku bibliotek linkowanych statycznie odpowiednie funkcje są w trakcie kompilacji (linkowania) dołączane do pliku z programem wynikowym.
Powyższa metoda powoduje jednak pewien problem. Naprawa błędu znalezionego w bibliotece wymaga powtórnej kompilacji wszystkich powiązanych
aplikacji, a kod wynikowy zajmuje miejsce (na dysku, jak i w pamięci) wielokrotnie. Rozwiązaniem są biblioteki łączone dynamicznie.
W tym przypadku w pliku programu są zapisywane wyłącznie odwołania, a same funkcje znajdują się w bibliotece (w przypadku Linuksa są to
zwykle pliki z rozszerzeniem .so
, znajdujące się w katalogu lib
, a w przypadku Windows są to pliki z rozszerzeniem .DLL
).
W przypadku programów zlinkowanych dynamicznie możemy sprawdzić od jakich bibliotek zależy (i czy wszystkie są dostępne):
$ ldd /bin/bash
linux-vdso.so.1 (0x00007ffd6f155000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007f08d9934000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f08d9730000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f08d9391000)
/lib64/ld-linux-x86-64.so.2 (0x00007f08d9b5e000)
Z powyższego wynika, że program bash jest połączony dynamicznie m.in. z biblioteką C (libc.so.6
). Aby dołączyć
do własnego programu bibliotekę, dodajemy do wywołania kompilatora opcję -lnazwaBiblioteki
, np.
gcc -Wall -ansi -lm -o program program.c
dołączy do naszego programu bibliotekę matematyczną (jeżeli dodalibyśmy jeszcze nagłówek math.h
, to moglibyśmy korzystać
z funkcji tej biblioteki).
Sprawdź rozmiar pliku program
przed i po dołączeniu biblioteki libm
.
Uwaga: Niektóre programy muszą (a co najmniej powinny) być jednak łączone statycznie. Przykładem takiego polecenia jest m.in.
ldconfig
służący do konfiguracji linkera dynamicznego. Innym przykładem mogą być polecenia (np. powłoka) trybu awaryjnego,
które w przypadku braku dostępu do dysku, nie mogłyby załadować podczas startu zależności (np. busybox
- programik zastępujący
praktycznie wszystkie podstawowe polecenia systemowe).
Zadania domowe
Zadanie domowe 1
Napisz program dodaj.c
(w języku ANSI C), który po wywołaniu z parametrami będącymi dwoma liczbami całkowitymi zwróci ich sumę, np.
$ ./dodaj 10 20
30
Uwaga: w programie użyj argc
i argv
.
Zadanie domowe 2
Do programu z poprzedniego zadania stwórz plik Makefile
(taki, jak w Zadaniu 4 z ćwiczeń).
Zadanie domowe 3
Napisz kolejny plik Makefile
, który stworzy pakiet .tar.gz
zawierający źródła programu dodaj
wraz z plikiem Makefile
(tym z zadania 2) w taki sposób,
by odpowiednie archiwum (dodaj.tar.gz
) było ponownie tworzone wyłącznie w przypadku, gdy któryś z plików uległ zmianie). Uwaga na dwa różne pliki Makefile
o tej samej nazwie!
Struktura katalogów:
dodaj-numer_indeksu/
|-- dodaj.c
|-- Makefile
Materiały uzupełniające
Dodatkowe informacje można znaleźć na stronie mgra Przybylskiego w module 6 i 7.1.
Przygotowanie do kolejnych zajęć
W ramach przygotowania do kolejnych zajęć proszę przerobić:
- ze strony Linux Journey materiały z sekcji Processes oraz Process Utilization,
- materiały o wskaźnikach i referencjach w języku C.