1. Procesy i współbieżność



Podobne dokumenty
Łącza nienazwane(potoki) Łącza nienazwane mogą być używane tylko pomiędzy procesami ze sobą powiązanymi.

Instrukcja do laboratorium Systemów Operacyjnych. (semestr drugi)

Procesy. Systemy Operacyjne 2 laboratorium. Mateusz Hołenko. 9 października 2011

Kolejki FIFO (łącza nazwane)

1.1 Definicja procesu

IPC: Kolejki komunikatów

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

Systemy Operacyjne 1 Laboratorium 2 Procesy i sygnały w Linuksie (jeden tydzień) dr inż. Arkadiusz Chrobot

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

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

Linux: Procesy. Systemy Operacyjne. Mateusz Hołenko. 26 marca 2013

Pętle i tablice. Spotkanie 3. Pętle: for, while, do while. Tablice. Przykłady

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

Argumenty wywołania programu, operacje na plikach

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

4. Procesy pojęcia podstawowe

Instrukcja do laboratorium Systemów Operacyjnych. (semestr drugi)

Programowanie współbieżne Wykład 10 Synchronizacja dostępu do współdzielonych zasobów. Iwona Kochańska

Autor: dr inż. Zofia Kruczkiewicz, Programowanie aplikacji internetowych 1

Mechanizmy pracy równoległej. Jarosław Kuchta

w odróżnieniu od procesów współdzielą przestrzeń adresową mogą komunikować się za pomocą zmiennych globalnych

Łącza nienazwane(potoki)

Działanie systemu operacyjnego

Spis treści. Rozdział 1. Aplikacje konsoli w stylu ANSI C i podstawowe operacje w Visual C

5. Model komunikujących się procesów, komunikaty

Działanie systemu operacyjnego

1 Podstawy c++ w pigułce.

Obsługa plików Procesy

Poniższe funkcje opisane są w 2 i 3 części pomocy systemowej.

Laboratorium Systemów Operacyjnych. Ćwiczenie 4. Operacje na plikach

Wątek - definicja. Wykorzystanie kilku rdzeni procesora jednocześnie Zrównoleglenie obliczeń Jednoczesna obsługa ekranu i procesu obliczeniowego

Aplikacja Sieciowa wątki po stronie klienta

Podstawy programowania skrót z wykładów:

Komunikacja za pomocą potoków. Tomasz Borzyszkowski

4. Procesy pojęcia podstawowe

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

Działanie systemu operacyjnego

Programowanie w języku C++

Semafory, pamięć dzielona i kolejki komunikatów

System operacyjny MACH

Działanie systemu operacyjnego

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

Podstawy programowania. Wykład: 5. Instrukcje sterujące c.d. Stałe, Typy zmiennych c.d. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

Procesy i wątki. Blok kontrolny procesu. Proces. Proces - elementy. Stan procesu

Systemy Operacyjne 1 Laboratorium 3 Potoki i łącza nazwane w Linuksie (jeden tydzień) dr inż. Arkadiusz Chrobot

Wykład 3. Procesy i wątki. Wojciech Kwedlo, Wykład z Systemów Operacyjnych -1- Wydział Informatyki PB

Procesy i wątki. Blok kontrolny procesu. Proces. Proces - elementy. Stan procesu. Blok kontrolny procesu

4. Komunikacja pomiędzy procesami przez łącza nienazwane i nazwane

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

Proces y i y w i ąt ą ki

Podstawy Programowania

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

Podstawy Programowania Podstawowa składnia języka C++

Stan procesu. gotowy - czeka na przydział procesora, zakończony - zakończył działanie.

ĆWICZENIE 5. TEMAT: OBSŁUGA PORTU SZEREGOWEGO W PAKIECIE KEILuVISON WYSYŁANIE PORTEM SZEREGOWYM

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

Laboratorium systemów operacyjnych ćwiczenie nr 3. [ilość modułów: 1] Temat zajęć: Procesy w systemie operacyjnym

Programowanie systemów czasu rzeczywistego laboratorium. Ćwiczenie 2. Temat zajęć: pakiety, zadania, synchronizacja czasowa, mechanizm spotkań

Ćwiczenie 4. Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1.

lekcja 8a Gry komputerowe MasterMind

Języki programowania. Przetwarzanie plików amorficznych Konwencja języka C. Część siódma. Autorzy Tomasz Xięski Roman Simiński

Podstawy i języki programowania

Aplikacje w Javie- wykład 11 Wątki-podstawy

Wskaźniki i dynamiczna alokacja pamięci. Spotkanie 4. Wskaźniki. Dynamiczna alokacja pamięci. Przykłady

Klient-Serwer Komunikacja przy pomocy gniazd

4.2 Sposób korzystania z l acza

Temat zajęć: Tworzenie i obsługa wątków.

Pliki. Funkcje tworzące pliki i operujące na nich opisane są w części 2 pomocy systemowej. Tworzenie i otwieranie plików:

Podstawy programowania w języku C++

Podstawy informatyki. Elektrotechnika I rok. Język C++ Operacje na danych - wskaźniki Instrukcja do ćwiczenia

Laboratorium z systemów operacyjnych. System plików - funkcje systemowe. Anna Wojak

Języki programowania C i C++ Wykład: Typy zmiennych c.d. Operatory Funkcje. dr Artur Bartoszewski - Języki C i C++, sem.

1 Zapoznanie się ze środowiskiem Xenomai.

Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1. Kraków 2013

ISO/ANSI C - funkcje. Funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje

1. Liczby i w zapisie zmiennoprzecinkowym przedstawia się następująco

> C++ dynamiczna alokacja/rezerwacja/przydział pamięci. Dane: Iwona Polak. Uniwersytet Śląski Instytut Informatyki

Wstęp do Programowania, laboratorium 02

Wskaźniki w C. Anna Gogolińska

Instrukcja do laboratorium Systemów Operacyjnych (semestr drugi)

Zmienne powłoki. Wywołanie wartości następuje poprzez umieszczenie przed nazwą zmiennej znaku dolara ($ZMIENNA), np. ZMIENNA=wartosc.

1 Podstawy c++ w pigułce.

Instrukcje sterujące. wer. 11 z drobnymi modyfikacjami! Wojciech Myszka :53:

Języki C i C++ Wykład: 2. Wstęp Instrukcje sterujące. dr Artur Bartoszewski - Języki C i C++, sem. 1I- WYKŁAD

Materiał. Typy zmiennych Instrukcje warunkowe Pętle Tablice statyczne Funkcje Wskaźniki Referencje Tablice dynamiczne Typ string Przeładowania funkcji

SYSTEMY OPERACYJNE WYKLAD 6 - procesy

10. Synchronizacja użycia zasobów, Semafory Problem producenta i konsumenta

Elementy języka C. ACprogramislikeafastdanceonanewlywaxeddancefloorbypeople carrying razors.

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

Zmienne i struktury dynamiczne

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

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi

SYSTEMY CZASU RZECZYWISTEGO - VxWorks

Wykład 8: klasy cz. 4

Programowanie współbieżne i rozproszone

Język C++ zajęcia nr 2

Wskaźniki. Informatyka

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

Programowanie równoległe i rozproszone. Monitory i zmienne warunku. Krzysztof Banaś Programowanie równoległe i rozproszone 1

Transkrypt:

1. Procesy i współbieżność Opracował: Sławomir Samolej Politechnika Rzeszowska, Katedra Informatyki i Automatyki, Rzeszów, 2013. 1.1. Wprowadzenie Proces to przestrzeń adresowa i pojedynczy wątek sterujący, który działa w tej przestrzeni, oraz potrzebne do tego zasoby systemowe. Minimalne zasoby do wykonywania się procesu to: procesor, pamięć i urządzenia wejścia-wyjścia. We współczesnych wielozadaniowych systemach operacyjnych w istocie każda instancja działającego programu jest procesem. Podczas uruchamiania programu w systemie operacyjnym następuje przeniesienie kodu programu z jakiegoś nośnika (najczęściej systemu plików) do pamięci operacyjnej. Kod programu jest otaczany pewnymi strukturami danych identyfikującymi go na czas wykonywania i zapewniającymi jego ochronę (tzw. blok kontrolny procesu). Następuje także powiązanie (planowanie przydziału) z programem zasobów systemu mikroprocesorowego, z których będzie korzystał. Zasobami przyszłego procesu są czas procesora, pamięć, system plików oraz urządzenia wejścia-wyjścia. Tak przygotowany program staje się procesem, który jest gotowy do wykonywania. Procesy w systemie operacyjnym tworzą drzewo (rys. 1). Każdy proces ma dokładnie jeden proces-rodzic. Procesy mogą posiadać wiele procesówdzieci. W systemach uniksowych (w tym Linux) wszystkie procesy są dziećmi pewnego pierwotnego procesu (Init). Procesy wykonywane są współbieżnie. Są albo przydzielane do różnych rdzeni procesora, albo wykonywane naprzemiennie na jednym procesorze w taki sposób, że użytkownik ma wrażenie, jakby wykonywały się ciągle. Rys. 1. Drzewo procesów systemu operacyjnego. Podstawowymi usługami systemu operacyjnego są uruchamianie i nadzorowanie procesów. Istnieje również możliwość zatrzymywania (typowego lub awaryjnego) procesu, jak również monitorowania wykonywanych procesów. Kolejną usługą systemu jest dostarczenie mechanizmów komunikacji i synchronizacji procesów. Komunikacja pozwala na przesyłanie danych pomiędzy działającymi procesami, zaś synchronizacja to możliwość decydowania, kiedy pewne porcje obliczeń

S. Samolej: Procesy i współbieżność 2 mogą się odbywać w zależności od obliczeń wykonanych przez inne procesy. W dalszej części opracowania pokazane zostaną podstawowe programy monitorujące i zarządzające procesami oraz elementarne techniki komunikacji i synchronizacji pomiędzy procesami w systemie Linux. 1.2. Narzędzia do monitorowania systemu i procesów Najbardziej uniwersalnymi narzędziami do monitorowania systemu Linux są pewne polecenia konsoli. W tabeli 1 wymienione zostały najważniejsze z nich. Tab. 1. Wybrane polecenia konsoli do monitorowania stanu systemu. Nazwa Opis ps warianty wywołania: ps ef ps axjf ps elf Top pstre Nice Renice kill pobieranie informacji o aktywnych procesach wszystkie procesy w systemie drzewo procesów informacja o wątkach dynamiczna lista aktywnych procesów w systemie drzewo procesów w systemie uruchomienie programu z zadanym priorytetem zmiana priorytetu uruchomionego procesu przesłanie sygnału do procesu pracującego w systemie operacyjnym (domyślnie jest to sygnał nakazujący zakończenie pracy procesu) Za pomocą wymienionych poleceń istnieje możliwość analizy systemu operacyjnego jako zbioru wykonywanych procesów. Pewne polecenia pozwalają na usuwanie procesów z systemu (np. kill) lub modyfikowanie ich priorytetów (np. nice, renice). W większości interfejsów graficznych systemu Linux dostępne jest również narzędzie o nazwie Monitor sytemu (w wersji Linux LUbuntu: Menadżer zadań). Pozwala ono na monitorowanie procesów na poziomie interfejsu graficznego. 1.3. Tworzenie aplikacji wieloprocesowych W systemach uniksowych istnieje możliwość rozgałęzienia programu na dwa (lub więcej) współbieżnie wykonywane procesy. Służy do tego specjalna funkcja o nazwie fork(). Schemat programu, w którym następuje rozgałęzienie pokazano na rysunku 2. #include <unistd.h> pid_t pid; pid = fork(); if(pid==-1) /*Błąd*/ if(pid==0) /* Kod procesu-dziecka */ else /* Kod procesu-rodzica */ Rys. 2. Technika rozgałęziania procesów z zastosowaniem instrukcji fork().

S. Samolej: Procesy i współbieżność 3 Rozgałęzienie procesu na proces macierzysty i na proces potomny następuje po wywołaniu funkcji fork(). Jeśli funkcja zwróci wartość -1, to rozgałęzienie zakończyło się fiaskiem. Jeśli rozgałęzienie zakończyło się sukcesem, to wartość zwrócona przez funkcję fork() informuje nas, w którym procesie w danej chwili jesteśmy. Jeśli funkcja zwróciła 0, to jesteśmy w procesie potomnym (dziecku), jeśli funkcja zwróciła inną wartość, to jesteśmy w procesie-rodzicu. Należy zwrócić uwagę, że tworzony jest jeden program, który opisuje zachowanie dwu (lub kilku) procesów. W szablonie na rysunku 1 pokazano, jak zidentyfikować instrukcje wykonywane przez rodzica, a jak te wykonywane przez dziecko z zastosowaniem instrukcji if. Kod źródłowy 1 zawiera pełny program, w którym następuje rozdzielenie na dwa procesy. Każdy z procesów pięciokrotnie wypisuje pewien tekst na ekranie i zawiesza swoje działanie na 1 sekundę (sleep(1)). Warto zwrócić uwagę na fakt, że po rozdzieleniu programu z zastosowaniem instrukcji fork(), proces potomny dziedziczy po procesie-rodzicu wszystkie zmienne i ewentualne uchwyty do kanałów komunikacyjnych i plików. Procesy jednak nie współdzielą tych zmiennych. Każdy z nich ma dostęp do swojej kopii zmiennych lokalnych i globalnych. Funkcja exit() służy do prawidłowego kończenia procesów. Kod źródłowy 1. Program tworzący 2 procesy. #include <sys/wait.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> int main() pid_t pid; int i; printf("start programu\n"); pid = fork(); if(pid==-1) exit(exit_failure); if(pid==0) for(i=0;i<5;i++) printf("tu dziecko\n"); sleep(1); else for(i=0;i<5;i++) printf("tu rodzic\n"); sleep(1); 1.4. Komunikacja W systemach uniksowych możliwe jest zorganizowanie komunikacji pomiędzy procesami na wiele sposobów. Jednym z prostszych jest zastosowanie potoków. Potok tworzy się za pomocą specjalnej funkcji pipe(), do której przekazywana jest dwuelementowa tablica liczb typu całkowitego. Kiedy funkcja jest wywoływana, wypełnia ona tę tablicę specjalnymi wartościami, będącymi uchwytami do potoku (systemowego kanału komunikacyjnego). Dwa zwrócone uchwyty połączone są w specjalny sposób. Wszystkie dane zapisane przy pomocy uchwytu 1 mogą być odczytane z

S. Samolej: Procesy i współbieżność 4 wykorzystaniem uchwytu 0. Przesyłanie danych z i do takiego potoku musi się odbywać z zastosowaniem funkcji read(), write(). Kod źródłowy 2 reprezentuje pełny program, w którym jeden proces wysyła dane do drugiego z zastosowaniem potoku. Kod źródłowy 2. Komunikacja między procesami z zastosowaniem potoku. #include <sys/wait.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> int main() int potoki[2]; char dane_wysylane[10] = "0"; char dane_odbierane[10] = "0"; int dane_przetworzone = 0; pid_t pid; int pipe_result; int i; pipe_result=pipe(potoki); if(pipe_result!=0) exit(exit_failure); pid = fork(); if(pid==-1) exit(exit_failure); if(pid==0) for(i=0;i<5;i++) dane_przetworzone = read(potoki[0], dane_odbierane, 10); printf("odczytano %s bajtów: %d\n", dane_odbierane, dane_przetworzone); sleep(1); else for(i=0;i<5;i++) dane_przetworzone = write(potoki[1], dane_wysylane, 10); printf("wyslano %d bajtów\n", dane_przetworzone); dane_wysylane[0]++; Jest to modyfikacja programu podanego w kodzie źródłowym 1. W programie jest zdefiniowana tablica potoki do przechowywania uchwytów do kanału komunikacyjnego. Tablice dane_wysyłane, dane_odbierane oraz zmienna dane_przetworzone są stosowane jako bufory, które odpowiednio zawierają: dane do wysłania, dane odebrane, informację ile danych przesłano. Zmienna pid służy do rozpoznawania, w którym procesie wykonywane jest przetwarzanie, zaś zmienna pipe_result pozwala na przechwycenie rezultatu działania funkcji pipe() i sprawdzenie, czy potok został prawidłowo zdefiniowany. W programie następuje najpierw utworzenie potoku, a następnie rozdzielenie na dwa procesy. Ponieważ proces potomny dziedziczy zmienne po procesierodzicu, otrzymuje on dostęp do kanału komunikacyjnego zdefiniowanego przez rodzica (tablica

S. Samolej: Procesy i współbieżność 5 potoki u dziecka zawiera już wcześniej utworzone uchwyty do potoku). Proces-dziecko próbuje 5- krotnie odczytać dane z potoku (wywołanie funkcji read()), przy czym po każdym odczycie zawiesza swoje wykonywanie na 1 sekundę. Proces rodzica pięciokrotnie wysyła dane do potoku (wywołanie funkcji write()). Opisy nowych funkcji zastosowanych w kodzie źródłowym 2 zawarto w tablicy 2. Tab. 2. Specyfikacje wybranych funkcji zastosowanych w kodzie źródłowym 2. int pipe(int potoki[2]); potoki[] tablica uchwytów do potoku wypełniania przez funkcję pipe Funkcja zwraca: 0, jeśli utworzenie potoku zakończyło się sukcesem, kod błędu w przeciwnym wypadku size_t write(int fildes, const void *buf, size_t nbytes); fildes uchwyt do pliku/potoku buf bufor z danymi do zapisu nbytes ilość danych do zapisu Funkcja zwraca ilość zapisanych bajtów, 0 gdy koniec pliku, -1 gdy błąd size_t read(int fildes, void *buf, size_t nbytes); fildes uchwyt do pliku/potoku buf bufor na dane nbytes maksymalna ilość bajtów do odczytania Funkcja zwraca ile bajtów odczytała, 0 gdy nic nie przeczytano koniec pliku, -1 gdy błąd. 1.5. Synchronizacja Synchronizacja to wypełnienie ograniczeń dotyczących kolejności wykonywania pewnych akcji przez procesy (np. pewna akcja wykonywana przez jeden proces może nastąpić tylko wtedy, gdy pewna inna akcja została wykonana w innym procesie). Podstawowym mechanizmem umożliwiającym synchronizację procesów jest semafor. Semafor S jest obiektem systemu operacyjnego, z którym związany jest licznik L zasobu przyjmujący wartości nieujemne. Na semaforze zdefiniowane są operacje atomowe (takie, których nie może przerwać żadne zdarzenie w systemie operacyjnym) sem_init, sem_wait i sem_post. Definicje operacji na semaforze pokazano w tabeli 3. Tab. 3. Definicje operacji na semaforze. Operacja Oznaczenie Opis Inicjalizacja semafora S sem_init(s,n) Ustawienie licznika semafora S na początkową wartość N. Zajmowanie sem_wait(s) Gdy licznik L semafora S jest dodatni (L>0), zmniejsz go o 1 (L=L 1). Gdy licznik L semafora S jest równy zero (L=0), zablokuj proces bieżący. Sygnalizacja sem_post(s) Gdy istnieje jakiś proces oczekujący na semaforze S, to odblokuj jeden z czekających procesów. Gdy brak procesów oczekujących na semaforze S, zwiększ jego licznik L o 1 (L=L+1).

S. Samolej: Procesy i współbieżność 6 Schemat posługiwania się semaforem do synchronizacji pracy pomiędzy dwoma procesami pokazano na rysunku 3. Celem synchronizacji jest zapewnienie, że instrukcja Y wykona się po zakończeniu instrukcji A, przy czym instrukcje A i Y należą do różnych współbieżnie wykonywanych procesów. W celu zapewnienia takiej synchronizacji należy powołać do życia semafor i zainicjować go wartością początkową 0. Możliwe są dwa scenariusze. W pierwszym instrukcja X wykona się szybciej, niż instrukcja A i w konsekwencji instrukcja sem_wait() wykona się wcześniej niż instrukcja sem_post(). Spowoduje to zatrzymanie pracy procesu P1 do momentu zakończenia instrukcji A i wykonania instrukcji sem_post() w procesie P2. Taką sekwencję synchronizacji ilustruje przebieg czasowy znajdujący się po lewej stronie rysunku 3. W drugim scenariuszu założono, że instrukcja A wykona się przed zakończeniem instrukcji X. W konsekwencji operacja sem_post() wykona się przed wykonaniem operacji sem_wait(). W tym przypadku proces P1 nie zostanie zatrzymany, ponieważ przed wykonaniem instrukcji sem_wait() semafor zostaje zwiększony o 1. W każdym przypadku zapewnione jest osiągnięcie założonego celu (instrukcja Y rozpoczyna wykonywanie po zakończeniu instrukcji A). sem_init(cosyn, 1, 0) /* wartość początkowa 0 */ P2() /* process sygnalizujący */ instrukcja A; sem_post (consyn) instrukcja B; P1() /* process czekający */ instrukcja X; sem_wait (consyn) instrukcja Y; Rys. 3. Synchronizacja procesów z zastosowaniem semafora. Kod źródłowy 3 pokazuje sposób realizacji synchronizacji 2 procesów z zastosowaniem semaforów. Program stosuje semafory z biblioteki pthreads. Musi być on skompilowany z opcją kompilatora -lpthread. Funkcja sem_open() tworzy semafor. Funkcja sem_init() ustala jego początkową wartość. W programie proces-dziecko oczekuje w pętli niekończonej na sygnalizację semafora, która odbywa się pięciokrotnie w procesie-rodzicu. Komunikat Nastąpiła synchronizacja jest wysyłany na konsolę po synchronizacji. Tabela 4 zawiera specyfikację wybranych funkcji biblioteki pthreads, sterujących pracą semaforów. Tab. 4. Wybrane funkcje sterujące semaforami w bibliotece pthreads. Utworzenie semafora: sem_t *sem_open(const char *name, int oflag, );

S. Samolej: Procesy i współbieżność 7 name nazwa semafora w systemie, powinna zacząć się od znaku / oflag jest ustawiana na O_CREAT, gdy chcemy utworzyć semafor (jeśli dodamy flagę O_EXCL funkcja zwróci błąd, w przypadku, gdy taki semafor już istnieje) mode_t ustalenie kontroli dostępu do semafora value ustalenie wartości początkowej semafora Funkcja zwraca uchwyt do semafora. Inicjalizacja semafora: int sem_init(sem_t *sem, int pshared, unsigned int value); pshared 0 - semofor jest dzielony pomiędzy wątki, >0 - może być dzielony pomiędzy procesy value początkowa wartość semafora Czekanie na semaforze: int sem_wait(sem_t *sem); Sygnalizacja: int sem_post(sem_t *sem); Kod źródłowy 3. Synchronizacja 2 procesów z zastosowaniem semafora. #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/file.h> #include <sys/times.h> #include <semaphore.h> int main() int a=0,i; pid_t pid; sem_t *sem; sem=sem_open("/thesem", O_CREAT); sem_init(sem, 1, 0); pid = fork(); if(pid==-1) exit(exit_failure); if(pid==0) while(1) sem_wait(sem); printf("nastapila synchronizacja\n"); else for(i=0;i<5;i++) printf("zaraz zezwole na odblokwanie drugiego procesu...\n"); sem_post(sem); sleep(1);

S. Samolej: Procesy i współbieżność 8 1.6. Proponowany przebieg ćwiczenia 1. Uruchomić konsolę i przetestować działanie poleceń ps, top, pstree na domyślnym zbiorze procesów w systemie Linux. Uruchomić polecenie: man ps oraz man top w celu zrozumienia, jakie parametry procesów są wyświetlane w poszczególnych kolumnach odpowiedzi polecenia ps i top. 2. Napisać program wykonujący pętlę nieskończoną, np.: int main() while(1); return 0; Uruchomić program i zaobserwować jego zachowanie w systemie z zastosowaniem poleceń ps, top, pstree oraz menadżera zadań. Usunąć proces za pomocą polecenia kill (w poleceniu należy podać numer PID procesu, który chcemy zabić ). Do usunięcia procesu można się posłużyć drugą konsolą. 3. Uruchomić przykładową aplikację two_processes.c. Zaobserwować, czy z chwilą jej uruchomienia rzeczywiście w systemie następuje utworzenie dwu nowych procesów. Aby wydłużyć działanie aplikacji, można zwiększyć ilość wykonywanych pętli. 4. Uruchomić przykładową aplikację two_processes_pipe.c. Zwrócić uwagę, w jaki sposób następuje przesyłanie danych pomiędzy procesami. Zmodyfikować aplikację w taki sposób, aby dane były nadawane co 5 sekund. Jak to wpłynie na tempo odbierania danych i zachowanie procesu odbierającego? 5. Uruchomić przykładową aplikację two_processes_sync.c. Zwrócić uwagę, w jaki sposób zrealizowana jest synchronizacja dwu procesów. 6. Zaproponować program, który tworzy 2 procesy. Pierwszy proces w sposób nieskończony generuje kolejne liczby parzyste i wysyła je na konsole, drugi w sposób nieskończony kolejne liczby nieparzyste i wysyła je na konsolę. Pierwszy proces po wygenerowaniu liczby oczekuje 2 sekundy, drugi 3. Po pewnym czasie zabić jeden z procesów. 7. Zaproponować program, który stworzy 3 procesy. Pierwszy, co 1 sekundę wypisuje tekst Pozdrowienia, drugi co 2 sekundy Czesc, a trzeci co 5 sekund Witam. 1.7. Literatura [1] Linux : programowanie / Neil Matthew, Richard Stones, RM, 1999 [2] Linux. Niezbędnik programisty/ John Fusco, Helion 2009 [3] Programowanie w Linuksie / K. Kuźniar, K. Lal, T. Rak, Helion, 2012