Programowanie w systemie UNIX CELE: dr inż. Paweł TURCZA Celem przedmiotu jest zapoznanie studenta z metodami i narzędziami wykorzystywanymi w tworzeniu oprogramowania dla systemów UNIX i Linux. Program: 1) elementy UNIX-a: system plików, shell 2) narzędzia służące kompilacji i testowaniu programów (gcc, make, gdb) 3) procesy, wątki, synchronizacja, komunikacja między procesami (mpi) 4) komunikacja z wykorzystaniem protokół TCP/IP 5) korzystanie z urządzeń w systemach unixowych 6) biblioteka Qt + zaawansowane konstr. języka C++ (funkcje virtualne, polimorfizm, szablony, STL) 7) Python Literatura M. Kerrisk, The Linux Programming interface (A Linux and UNIX System Programming Handbook) N. Matthew, R. Stones, Beginning Linux Programming, 3ed http://tldp.org/ldp/bash-beginners-guide/html/index.html B Eckel, Thinking in C++, 2nd ed. Volume 1 & 2 M. Bach, Budowa systemu operacyjnego UNIX M. Rochkind, Programowanie w systemie UNIX dla zaawansowanych
Historia systemów UNIX 1969 pierwsza implementacja wykonana przez Kena Thompson'a w Bell Laboratories w assemblerze (PDP-7) nowe idee drzewiasty system plików program powłoki (shell) do interpretacji komend użytkownika pojęcie pliku jako ciągu bajtów Kolejne wydania: First Ed., listopad 1971: Second Ed., czerwiec 1972: Third Ed., luty 1973: Fourth Ed., listopad 1973: Fifth Ed., czerwiec 1974: Sixth Ed., maj 1975: (MULTICAST) kompilator FORTRAN'u programy: ar, cat, chmod, chown, cp, dc, ed, find, ln, ls, mail, mkdir, mv, rm, sh, su, and who. działa na 10 maszynach należących do AT&T. kompilator języka C i mechanizm potoków. pierwsza wersja napisana w języku C system działa na 50 maszynach. pierwsza wersja używana poza AT&T.
Zadania systemu operacyjnego Zadaniem systemu operacyjnego jest zarządzanie zasobami systemu komputerowego: zarządzanie procesami: UNIX implementuje tzw. preemptive multitasking tzn. wielozadaniowość z wywłaszczaniem tworzenie i uśmiercanie procesów: ładowanie do pamięci obrazu programu i przydział niezbędnych zasobów. zwolnienie zasobów po zakończeniu działania zadania zarządzanie pamięcią: mechanizm pamięci virtualnej Izolacja przestrzeni pamięciowych procesów od siebie, a także od przestrzeni jądra. Procesy nie mogą czytać ani modyfikować obszarów pamięci nie należących do nich. Stronicowanie - w pamięci fizycznej znajduje się tylko fragment kodu i danych każdego z zadań. Mechanizm ten pozwala to na lepsze wykorzystanie CPU, bo fragment programu, który ma być wykonywany najprawdopodobniej znajduje się już w pamięci operacyjnej. udostępnianie urządzeń systemowych: jądro dostarcza sterowników i spójnego API do urządzeń zainstalowanych w systemie kontrola dostępu do tychże urządzeń
Zadania systemu operacyjnego (c.d.) obsługa sieci: jądro wysyła i odbiera pakiety sieciowe na rzecz danego procesu kieruje (routing) pakiety do systemu docelowego dostarcza API dla tzw. wywołań systemowych: proces może żądać od systemu wykonania jakiegoś zadania Z punktu widzenia użytkownika zadaniem systemu operacyjnego jest dostarczenia abstrakcji wirtualnego osobistego komputera. Programy Aplikacje Shell narzędziowe Biblioteka funkcji systemowych Jądro systemu operacyjnego Sprzęt Użytkownicy Sterowniki Warstwowa struktura systemu http://www.ibm.com/developerworks/linux/library/l-linux-kernel/
Główne podsystemy jądra Linux'a Architektura jądra Wirtualny system plików
Struktura plików w Linuxie Typy plików: pliki zwykłe, urządzenia (devices), potoki (pipes), gniazdka (sockets), katalogi (directories), i linki (symbolic links). Uniwersalny system I/O: do operacji na plikach i urządzeniach służą te same funkcje open(), read(), write(), close(), i ioctl() /dev/console /dev/tty /dev/null - konsola systemowa - terminal kontrolny procesu - pożeracz
Struktura plików w Linuxie (2) # mount -t iso9660 /dev/hdc /mnt/cdrom # cd /mnt/cdrom $ echo do not want to see this >/dev/null $ cp /dev/null empty_file Deskryptor pliku: mała nieujemna liczb całkowita 0-stdin, 1-stdout, 2-stderr Urządzenia w Linuxie dzielone są na blokowe i znakowe
Prawa dostępu do plików Nadawanie i sprawdzanie praw dostepu: % chmod u=rw,g=r,o=x plik_testowy % ls -l plik_testowy -rw-r----x 1 pt users 0 Oct 11 09:27 plik_testowy Uwaga: użytkownik i członkowie jego grupy nadal maja prawo czytania pliku, prawo do wykonywania mają pozostali użytkownicy % chmod u=wx,g=r,o=x plik_testowy właściciel zyskał prawo do wykonywania, ale stracił do czytania??? Prawa dostępu kodowane ósemkowo (read=4, write=2, execute=1): % chmod 751 plik_testowy % ls -l plik_testowy -rwxr-x--x 1 pt users 21 Oct 11 09:31 plik_testowy % umask -S u=rwx,g=rx,o=rx The -S option causes the mask to be printed in symbolic form % umask 0022 % touch nowy_plik % ls -l nowy_plik -rw-r--r-- 1 pt users 0 Oct 11 09:40 nowy_plik Uwaga: przy tworzeniu zwykłych plików bit prawa wykonywania jest automatycznie kasowany.
% umask 0077 #zabezpiecza przed tworzeniem plików do których miałby dostęp ktoś poza #użytkownikiem (właścicielem) Co oznacza prawo do wykonania dla katalogu? % mkdir tmp % touch tmp/plik % ls -l tmp -rw-r--r-- 1 pt users 0 Oct 11 11:17 plik % chmod 600 tmp % ls -l tmp -?????????????? plik utwórzmy tmp/plik z poniższą zawartością echo '#!/bin/sh' > tmp/plik echo 'echo xyz' >> tmp/plik % chmod 300 tmp #prawo do pisania i wykonania (WX), brak R % ls -l tmp ls: cannot open directory tmp: Permission denied tmp/plik #plik można wykonać, jeśli się o nim wie
Struktura plików w Linuxie(3) funkcje read, write Deskryptor pliku mała liczba całkowita zwracana przez funkcję open. int open(const char *path, int oflags); int open(const char *path, int oflags, mode_t mode); Drugi parametr funkcji open może przyjmować: O_RDONLY (tylko czytanie), O_WRONLY (tylko pisanie), lub O_RDWR (czytanie i pisanie) O_APPEND tryb dopisywania O_TRUNC obetnij długość do 0 O_CREAT utwórz Ostatni parametr funkcji open to 9 bitów praw dostępu dla tworzonego pliku (np. ósemkowo 0755).
Struktura plików w Linuxie (3) #include <unistd.h> //intro/write.c #include <stdlib.h> int main() { if ((write(1, "Here is some data\n", 18))!= 18) write(2, "A write error has occurred on file descriptor 1\n",46); exit(0); } Demonstracja mechanizmu przekierowania wyjścia (poprzez uruchomienie powyższego programu w różny sposób a.out >output a.out >output 2>&1 # bez spacji pomiędzy 2 a > a.out 1>stdio # bez spacji pomiędzy 1 a > a.out 2>stderr # bez spacji pomiędzy 2 a >
Struktura plików w Linuxie(3) funkcje read, write #include <fcntl.h> #include <stdio.h> #define BUFSIZE 1 int main() /* copy input to output */ { char buf[bufsize]; int n; } //intro/copy.c int fd = open("./rw.c", O_RDONLY); if(fd<0) { printf("open: blad"); return -1; } while ((n = read(fd, buf, BUFSIZE)) > 0) write(1, buf, n); n = read(fd, buf, BUFSIZE); printf("n=%d", n); Funkcja read zwraca liczbę faktycznie przeczytanych bajtów. W przypadku końca pliku jest to 0. Wartością -1 oznacza błąd. Kod błędu umieszczany jest w zmiennej errno (#include <errno.h>). Drugi parametr funkcji open może przyjmować: O_RDONLY (tylko czytanie), O_WRONLY (tylko pisanie), lub O_RDWR (czytanie i pisanie) O_APPEND tryb dopisywania O_TRUNC obetnij długość do 0 O_CREAT utwórz Ostatni parametr funkcji open to 9 bitów praw dostępu dla tworzonego pliku (np. ósemkowo 0755).
#include <stdio.h> #include <fcntl.h> #include <errno.h> #include <string.h> Struktura plików w Linuxie (4) //intro/open_dir.c #define BUFSIZE 1 main() /* próba czytania z katalogu */ { int fd = open("..", O_RDONLY); printf("fd=%d\n", fd); if(fd==-1) { printf("errno=%d: %s\n", errno, strerror(errno)); } char buf[bufsize]; int n; while ((n = read(fd, buf, BUFSIZE)) > 0) write(1, buf, n); } if(n==-1) { printf("errno=%d: %s\n", errno, strerror(errno)); }
Struktura plików w Linuxie (4) Gdy tworzymy nowy plik (O_CREAT) należy dodatkowo określić mu prawa dostępu (pole mode) za pomocą poniższych flag lub za pomocą liczby ósemkowej, jak poprzednio S_IRUSR: Read permission, owner S_IWUSR: Write permission, owner S_IXUSR: Execute permission, owner S_IRGRP: Read permission, group S_IWGRP: Write permission, group S_IXGRP: Execute permission, group S_IROTH: Read permission, others S_IWOTH: Write permission, others S_IXOTH: Execute permission, others open ( myfile, O_CREAT, S_IRUSR S_IXOTH); $ ls -ls myfile 0 -r -x 1 pt users 0 Sep 22 08:11 myfile Po pliku możemy się poruszać off_t lseek(int fildes, off_t offset, int whence); SEEK_SET SEEK_CUR SEEK_END
Informacji o danym pliku dostarczają: #include <unistd.h> #include <sys/stat.h> Struktura plików w Linuxie (5) int fstat(int fildes, struct stat *buf); int stat(const char *path, struct stat *buf); //info about the file to which the link refers int lstat(const char *path, struct stat *buf); //info about the link itself The lstat function is like stat, except that if the file referred to is a symbolic link, lstat tells about the link, not the file to which it refers.
Struktura plików w Linuxie (6) File type flags (st_mode) S_IFBLK: is a block special device S_IFDIR: is a directory S_IFCHR: is a character special device S_IFIFO: is a FIFO (named pipe) S_IFREG: is a regular file S_IFLNK: is a symbolic link File type makra (st_mode) S_ISBLK: Test for block special file S_ISCHR: Test for character special file S_ISDIR: Test for directory S_ISFIFO: Test for FIFO S_ISREG: Test for regular file S_ISLNK: Test for symbolic link Przykład użycia struct stat statbuf; mode_t modes; stat("myfile",&statbuf); modes = statbuf.st_mode; intro/fstat.c File type masks (st_mode) S_IFMT: File type S_IRWXU: User R/W/X permissions S_IRWXG: Group R/W/X permissions S_IRWXO: Others R/W/X permissions if(!s_isdir(modes) ) printf("not dir"); if( modes & S_IWGRP ) printf("s_iwgrp \n");
Struktura plików w Linuxie (7) (File and Directory Maintenance) #include <sys/stat.h> int chmod(const char *path, mode_t mode); int chown(const char *path, uid_t owner, gid_t group); int unlink(const char *path); int link(const char *path1, const char *path2); int symlink(const char *path1, const char *path2); int mkdir(const char *path, mode_t mode); int rmdir(const char *path); int chdir(const char *path); char *getcwd(char *buf, size_t size); // change the permissions // change the owner //hard link //soft link // change directory // current working directory (Scanning Directories) #include <dirent.h> DIR *opendir(const char *name); struct dirent *readdir(dir *dirp); closedir(dir *); //Struktura dirent zawiera m.in. następujące pola: ino_t d_ino: //The inode of the file char d_name[]: //The name of the file Przykład: intro/lsdir.c
System plików /proc W Linuxie istnieje specjalny system plików procfs (w pamięci nie na dysku). System ten dostępny jest zwykle w katalogu /proc. Zawiera on pliki specjalne, które służą do udostępniania informacji o stanie systemu. Programy, mogą odczytywać lub zapisywać te pliki stosownie do potrzeb i posiadanych uprawnień. $ cat /proc/cpuinfo $ cat /proc/meminfo $ cat /proc/version $ cat /proc/net/sockstat $ cat /proc/sys/fs/file-max $ ls -l /proc/4991 $ od -c /proc/4991/cmdline #od - dump files in octal and other formats $ ls /proc/4991/fd $ ls diff oldfilelist # porównaj wynik komendy ls z zawartością pliku $ ls diff /dev/fd/0 oldfilelist #/dev/fd/0 deskryptor standardowego wejścia