plik


ÿþSystemy Operacyjne  semestr drugi WykBad drugi Zarzdzanie procesami w Linuksie Podobnie jak w innych systemach operacyjnych w Linuksie wszystkie informacje zwizane z procesem s przechowywane w bloku kontrolnym procesu (deskryptorze procesu). Jego rozmiar wynosi 1,7 KB i jest to struktura typu  task_struct , w której cz[ pól stanowi wskazniki na inne struktury. Pami na deskryptor jest przydzielana przez alokator plastrowy1. W starszych wersjach Linuksa deskryptor byB przechowywany na koDcu stosu procesu przeznaczonego dla wywoBaD systemowych i znajdujcego si w przestrzeni jdra. Od wersji 2.6 na stosie przechowywana jest struktura  thread_info . Typ tej struktury jest zdefiniowany w pliku nagBówkowym <asm/thread_info.h> nastpujco2: sturct thread_info { struct task_struct *task; struct exec_domain *exec_domain; unsigned long flags; __u32 cpu; __s32 preempt_count; mm_segment_t addr_limit; struct restart_block restart_block; unsigned long previous_esp; __u8 supervisor_stack[0]; }; Linux podobnie jak inne systemu uniksowe przypisuje ka|demu procesowi unikatowy identyfikator okre[lany skrótem PID. Warto[ tego identyfikatora jest przechowywana w polu  pid deskryptora. Typ tego pola nazywa si  pid_t , a jego implementacja jest zale|na od architektury na której jdro pracuje. Ze wzgldu na kompatybilno[ z innymi uniksami pole to mo|e przyjmowa warto[ci caBkowite od 0 do 32767, cho zawsze mo|liwe jest zwikszenie tego zakresu. W jdrze zdefiniowana jest makrodefinicja o nazwie  current , która pozwala na szybki dostp do deskryptora bie|cego procesu. W architekturze x86 i pokrewnych dziaBanie tej makrodefinicji skBada si z dwóch etapów. Najpierw za pomoc funkcji  current_thread_info() ustalany jest adres struktury  thread_info bie|cego procesu, poprzez zamaskowanie 13 najmniej znaczcych bitów wskaznika stosu: movl $-8192, %eax andl %esp, %eax Nastpnie z tej struktury jest otrzymywany wskaznik na deskryptor bie|cego zadania: current_thread_info()->task; W deskryptorze procesu przechowywany jest równie|, w polu  state stan zadania. To pole mo|e przyjmowa jedn z po[ród piciu najwa|niejszych3 warto[ci: TASK_RUNNING  proces jest gotów do uruchomienia, ten stan nie oznacza jednak, |e w danej chwili proces jest wykonywany, TASK_INTERRUPTIBLE  proces zostaB zawieszony i oczekuje na jakie[ zdarzenie, mo|e on jednak zosta ustawiony w stan gotowo[ci przez inne zdarzenie ni| to, na które oczekiwaB, TASK_UNINTERRUPTIBLE  podobnie jak wy|ej, ale proces nie bdzie reagowaB na |adne inne zdarzenia, stan ten stosowany jest rzadko, gdy| uniemo|liwia np.: usunicie procesu z systemu, TASK_ZOMBIE4  proces zakoDczyB si, w systemie zostaB jednak jego deskryptor, który jest usuwany przez proces macierzysty poprzez wywoBanie o nazwie  wait4() , TASK_STOPPED  zadanie zostaBo zatrzymane po otrzymaniu odpowiedniego sygnaBu. Stan procesu mo|e zosta zmieniony za pomoc funkcji  set_task_state . Je[li zmiana ma dotyczy stanu bie|cego procesu, to mo|na u|y funkcji  set_current_state . Proces u|ytkownika wykonuje si w przestrzeni u|ytkownika. Aby móc skorzysta z usBug jdra mo|e wywoBa któr[ z funkcji zdefiniowanych w bibliotece (g)libc, które stanowi interfejs dla wywoBaD systemowych. Je[li dojdzie do realizacji takiego wywoBania, to mówimy, |e jdro wykonuje kod w kontek[cie procesu. W takim kontek[cie mo|liwe jest korzystanie z makrodefinicji  current . Po zakoDczeniu wywoBania dziaBanie procesu jest wznawiane, chyba, |e w systemie pojawiB si proces o wy|szym priorytecie. Procesy w systemach uniksowych tworz hierarchi, na której szczycie znajduje si proces o nazwie  init , o PID równym 1. PozostaBe procesy s jego potomkami. Deskryptor ka|dego procesu zawiera wskaznik o nazwie  parent na proces macierzysty, oraz wskaznik o nazwie  children na list wskazników na deskryptory zadaD potomnych. Aby uzyska deskryptor rodzica bie|cego zadania trzeba wykona nastpujcy kod: struct task_struct *task = current->parent; Aby przejrze list procesów potomnych bie|cego procesu nale|y wykona: sturct task_struct *task; struct list_head *list; list_for_each(list, &current->children) { task = list_entry(list, struct task_struct, sibling); } 1 DziaBanie alokatora plastrowego bdzie omówione na wykBadzie po[wiconym zarzdzaniu pamici. 2 Ta posta tego typu dotyczy wyBcznie architektury i386 i jdra 2.6.11 z dystrybucji Mandriva. 3 Tych warto[ci jest wicej, ale te s najwa|niejsze. W nowszych jdrach pojawiBy si warto[ci stanów, których nie byBo w wersjach poprzednich. 4 W nowszych wersjach jdra stan ten zostaB nazwany EXIT_ZOMBIE. W jeszcze nowszych wersjach jest on zapisywany w zupeBnie innym polu. 1 Systemy Operacyjne  semestr drugi Deskryptory procesów s powizane ze sob w dwukierunkow list procesów. Aby otrzyma wskaznik na deskryptor poprzedniego lub nastpnego zadania trzeba u|y odpowiednio makrodefinicje  prev_task(task) lub  next_task(task) . Istnieje równie| makrodefinicja  for_each_process(task) , która pozwala  przejrze wszystkie procesy na li[cie. Linux, tak jak pozostaBe systemy uniksowe pozwala na tworzenie nowych procesów za po[rednictwem funkcji fork() i vfork(). Dodatkowo w Linuksie mo|na utworzy wtek przy pomocy funkcji __clone(). Wszystkie te funkcje korzystaj z wywoBania systemowego  clone() . Funkcja fork() tworzy nowy proces, który wspóBdzieli z procesem macierzystym obszar kodu, zwany w uniksach obszarem tekstu, oraz obszar danych. Stosowana jest tu technika  copy_on_write , która pozwala na tak dBugie wspóBdzielenie przez procesy obszaru danych, dopóki jeden z nich nie zechce do niego zapisywa, wówczas ten obszar jest kopiowany i od tej chwili ka|dy z procesów dysponuje wBasnym obszarem danych. Aby nowy proces mógB wykona nowy kod nale|y wywoBa jedn z funkcji  exec() . Jak ju| wcze[niej zostaBo wspomniane  fork() wywoBuje  clone() , ono z kolei wywoBuje funkcj  do_fork() , która wywoBuje funkcj  copy_process() , do zadaD tej funkcji nale|y: utworzenie stosu jdra i deskryptora dla nowego procesu, sprawdzenie, czy utworzenie nowego procesu nie wyczerpie limitu zasobów okre[lonego dla u|ytkownika procesu, ustawienie procesu w stan TASK_UNINTERRUPTIBLE, ustawienie flag procesu, pozyskanie dla niego numeru PID, skopiowanie z uwzgldnieniem znaczników przekazanych do  clone() struktur zwizanych z zasobami i obsBug sygnaBów, podziaB czasu wykonania midzy proces potomny i macierzysty oraz zwrócenie wskaznika na nowy proces. Po wykonaniu tej funkcji nastpuje powrót do  do_fork() , która uruchamia proces potomka jako pierwszy. Funkcja vfork() zakBada, |e proces potomny wywoBa natychmiast po powstaniu funkcj  exec() i wstrzymuje wykonanie procesu macierzystego. Funkcja ta jest obecna w systemie ze wzgldów zwizanych z kompatybilno[ci, ale korzystanie z niej nie jest zalecane. W przeciwieDstwie do wielu innych systemów operacyjnych Linux obsBuguje wtki, ale nie odró|nia ich od zwykBych procesów. Zarówno jedne jak i drugie s tworzone przez wywoBanie systemowe  clone() . Ró|nica polega tylko na tym jakie parametry s przekazywane dla tego wywoBania. Poni|ej przedstawiono wszystkie mo|liwe warto[ci tych parametrów: CLONE_CLEAR_TID  zeruje warto[ TID, CLONE_DETACHED  proces macierzysty nie wysyBa przy zakoDczeniu dziaBania sygnaBu SIGCHLD, CLONE_FILES  procesy wspóBu|ytkuj otwarte pliki, CLONE_FS  procesy wspóBu|ytkuj informacje o plikach, CLONE_IDLETASK  zeruje warto[ PID dla zadaD jaBowych, CLONE_NEWNS  tworzona jest nowa przestrzeD nazw, dla procesu potomnego, CLONE_PARENT  PID rodzica jest kopiowane z procesu macierzystego (oba procesy maj to samo PID rodzica), CLONE_PTRACE  proces potomny bdzie [ledzony, tak jak proces macierzysty, CLONE_SETTID  zapisuje warto[ TDI do przestrzeni u|ytkownika, CLONE_SETTLS  tworzony jest nowy obszar TLS, dla procesu potomnego, CLONE_SIGHAND  kopiowane s do procesu potomnego procedury obsBugi sygnaBów, CLONE_SYSVSEM  oba procesy korzystaj z semantyki operacji SEM_UNDO charakterystycznej dla wersji System V, CLONE_THREAD  oba procesy bd w tej samej grupie wtków, CLONE_VFORK  powoduje, |e wywoBanie  clone() zachowuje si jak  vfork() , CLONE_VM  powoduje, |e procesy bd wspóBdzieliBy przestrzeD adresow. Równie| jdro mo|e tworzy wtki, je[li musi wykona jakie[ zadania w tle. PrzykBadami takich zadaD s wtki  ksoftirqd i  pdflush . Wtki jdra nie maj wBasnej przestrzeni adresowej, dziaBaj w obrbie przestrzeni jdra. Tworzone s za pomoc wywoBania funkcji o nazwie  kernel_thread 5, która wywoBuje  clone() , ale wikszo[ znaczników dla tego wywoBania jest zastpiona CLONE_KERNEL. Zazwyczaj wtki jdra w ptli wykonuj jak[ czynno[, a wic nie koDcz si do chwili przeBadowania systemu. Proces koDczy si wywoBujc (jawnie, bdz niejawnie) funkcj  exit() , która z kolei korzysta z wywoBania  do_exit() . To wywoBanie jest odpowiedzialne za zwolnienie wszystkich struktur zwizanych z procesem i powiadomienie procesu macierzystego o zakoDczeniu procesu potomnego. W systemie pozostaje jedynie deskryptor procesu i stos jdra wraz ze struktur  thread_info . Te dwie struktury s zwalniane przez funkcj  release_task() , z której korzysta wywoBanie  wait4() . Funkcja ta zmniejsza liczb procesów nale|cych do u|ytkownika, usuwa proces z tablicy haszujcej  pidhash i z listy zadaD, usuwa zadanie z listy procesów [ledzonych (o ile byBo ono [ledzone) oraz zwalnia pami przydzielon na struktury  task_struct i  thread_info . Je[li proces macierzysty zakoDczy si przed procesem potomnym, to ten ostatni pozostanie w stanie zombie. Aby unikn takiej sytuacji przydzielany jest mu nowy rodzic, który nale|y do tej samej grupy procesów lub jest procesem  init . PrzydziaB ten wykonuje funkcja  forget_original_parent() wywoBywana w ramach  do_exit() . Nowo[ci w jdrze 2.6 jest to, |e przeglda ona dwie listy procesów potomnych: list procesów zwykBych i list procesów [ledzonych. Na nastpnej stronie znajduje si kod moduBu jdra, który po zaBadowaniu i przed usuniciem przeglda za pomoc makrodefinicji for_each_process() list wszystkich procesów w systemie i wypisuje ich nazw, PID oraz stan, je[li jest on równy TASK_RUNNING, TASK_INTERRUPTIBLE, TASK_UNINTERRUPTIBLE lub TASK_STOPPED. Nazwa procesu jest zapisana w polu  comm deskryptora procesu. 5 W jdrze 2.6 istniej funkcje napisane przez Rusty Russella, które sBu| do obsBugi wtków jdra i s prostsze w u|yciu ni|  kernel_thread i spóBka. 2 Systemy Operacyjne  semestr drugi #include<linux/init.h> #include<linux/module.h> #include<linux/sched.h> MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Simple module that prints name, pid and state of every process."); MODULE_AUTHOR("Arkadiusz Chrobot <a.chrobot@tu.kielce.pl>"); static int __init init_tasklist(void) { struct task_struct *p; for_each_process(p) { printk(KERN_INFO "Process name is: %s, and its pid is: %i. ",p->comm, p->pid); if(p->state==TASK_RUNNING) printk("Process state is TASK_RUNNING\n"); if(p->state==TASK_INTERRUPTIBLE) printk("Process state is TASK_INTERRUPTIBLE\n"); if(p->state==TASK_UNINTERRUPTIBLE) printk("Process state is TASK_UNINTERRUPTIBLE\n"); if(p->state==TASK_STOPPED) printk("Proces state is TASK_STOPPED\n"); } return 0; } static void __exit exit_tasklist(void) { struct task_struct *p; for_each_process(p) { printk(KERN_INFO "Process name is: %s, and its pid is: %i. ",p->comm, p->pid); if(p->state==TASK_RUNNING) printk("Process state is TASK_RUNNING.\n"); if(p->state==TASK_INTERRUPTIBLE) printk("Process state is TASK_INTERRUPTIBLE.\n"); if(p->state==TASK_UNINTERRUPTIBLE) printk("Process state is TASK_UNINTERRUPTIBLE.\n"); if(p->state==TASK_STOPPED) printk("Proces state is TASK_STOPPED.\n"); } } module_init(init_tasklist); module_exit(exit_tasklist); 3

Wyszukiwarka

Podobne podstrony:
Wykłady Zarządzanie Procesami
SO2 wyklad Przestrzeń adresowa procesów
Zarzadzanie Procesami Surma Wyklad 4 ZP
Zarzadzanie Procesami Surma Wyklad 1 ZP
ZARZĄDZANIE PROCESAMI wykłady
Zarzadzanie Procesami Surma Wyklad 5 ZP
Zarzadzanie Procesami Surma Wyklad 3 ZP
Zarzadzanie Procesami Surma Wyklad 6 ZP
Zarzadzanie procesami Z4
M Janczarek Zarządzanie procesami produkcyjnymi w przedsiębiorstwie
Zarzadzanie procesami Program
SO2 wyklad 9
SO2 wyklad
Wyklad 1 Zarzadzanie finansami Wprowadzenie do finansow
wykład zarządcza rachunkowość
Metoda ABC jako narzędzie wspomagające zarządzanie procesowe w przedsiębiorstwie

więcej podobnych podstron