Procesy w systemach UNIX i Linux



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

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

2. Zarządzanie procesami

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

Model procesu w systemie Linux. Tomasz Borzyszkowski

Temat zajęć: Obsługa procesów w systemie.

Procesy. S. Samolej: Procesy

2. Zarządzanie procesami

Obsługa plików Procesy

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

2. Zarządzanie procesami

Uruchamianie programów w systemie Linux, potoki, strumienie, procesy, alias

procesy odrębne dzielone

Powłoka interpreter poleceń systemu UNIX

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

4. Procesy pojęcia podstawowe

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

Procesy. 5. Procesy (2005/2006)

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

Programowanie Współbieżne. W Linuxie/Unixie

pami eć operacyjna przechowuje dane do przetworzenia, tymczasowe dane pomocnicze,

4.2 Sposób korzystania z l acza

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

4. Procesy pojęcia podstawowe

Sygnały. 7. Sygnały (2005/2006)

Systemy operacyjne III

Systemy operacyjne Programowanie w języku powłoki sh

Zarządzanie Procesami

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

UXP1A Unix Programowanie i Architektura

4. Procesy pojęcia podstawowe

Łącza nienazwane(potoki)

1.1 Definicja procesu

2 Przygotował: mgr inż. Maciej Lasota

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

Systemy operacyjne / Programowanie w języku powłoki sh str.1/19

Moduł 4: Strumienie, potoki, sterowanie procesami

Działanie systemu operacyjnego

Pobieranie argumentów wiersza polecenia

Systemy operacyjne na platformach mobilnych 2 Podstawy obsługi powłoki Bash

Procesy, pliki, potoki, sygnały - uzupełnienie

przypadków wywo lanie systemowe (funkcja systemowa) lub funkcja biblioteczna zwraca wartość 1(czasamiNULL) iprzypisujezmiennej zewn etrznej,

Jądro Powłoka System plików Programy użytkowe

Powłoka (shell) Powłoka ksh

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

Zarządzanie procesami (omawiane zagadnienia)

Zarządzanie procesami

Systemy Operacyjne Ćwiczenia

SYSTEMY OPERACYJNE WYKLAD 6 - procesy

Działanie systemu operacyjnego

Procesy, wątki i zasoby

1 Przygotował: mgr inż. Maciej Lasota

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

Laboratorium Procesy w systemach UNIX 3.2 Polecenia związane z procesami

SUMA KONTROLNA (icmp_cksum) NUMER KOLEJNY (icmp_seq)

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

Powłoka I. Popularne implementacje. W stylu sh (powłoki zdefiniowanej w POSIX) W stylu csh. bash (najpopularniejsza) zsh ksh mksh.

Proces y i y w i ąt ą ki

Funkcja (podprogram) void

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

Systemy Operacyjne - Operacje na plikach

Pliki w C/C++ Przykłady na podstawie materiałów dr T. Jeleniewskiego

Funkcje systemu Unix

Biblioteka standardowa - operacje wejścia/wyjścia

Działanie systemu operacyjnego

Zarządzanie procesami i wątkami

Systemy operacyjne. Systemy operacyjne. Systemy operacyjne. Program wykładów. Strona WWW przedmiotu: Program ćwiczeń projektowych

J. Ułasiewicz Łącza nienazwane, nazwane, select 1

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

Instytut Teleinformatyki

Wielozadaniowość w systemie Microsoft Windows

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

Procesy, zasoby i wątki

Procesy, zasoby i wątki

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

Prezentacja systemu RTLinux

Programowanie proceduralne INP001210WL rok akademicki 2015/16 semestr letni. Wykład 6. Karol Tarnowski A-1 p.

PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO

Programowanie Proceduralne

Języki i metodyka programowania. Typy, operatory, wyrażenia. Wejście i wyjście.

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

Procesy, zasoby i wątki

41. System operacyjny. Postrzeganie systemu operacyjnego przez warstwę oprogramowania użytkowego

Języki i metodyka programowania. Wprowadzenie do języka C

Systemy Operacyjne I: Procesy

// Liczy srednie w wierszach i kolumnach tablicy "dwuwymiarowej" // Elementy tablicy są generowane losowo #include <stdio.h> #include <stdlib.

Zakład Systemów Rozproszonych

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

... Ireneusz Mrozek. Wydział Informatyki

Projektowanie oprogramowania systemów PROCESY I ZARZĄDZANIE PROCESAMI

Działanie systemu operacyjnego

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

Temat zajęć: Tworzenie skryptów powłoki systemu operacyjnego.

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

Funkcje zawarte w bibliotece < io.h >

POZNA SUPERCOMPUTING AND NETWORKING CENTER. Wprowadzenie do systemu operacyjnego Linux zarzdzanie procesami

System operacyjny Linux

Funkcje zawarte w bibliotece < io.h >

Instytut Teleinformatyki

SOE Systemy Operacyjne Wykład 8 Pamięć wirtualna dr inż. Andrzej Wielgus

Transkrypt:

SOE Systemy Operacyjne Wykład 5 Procesy w systemach UNIX i Linux dr inż. Andrzej Wielgus Instytut Mikroelektroniki i Optoelektroniki WEiTI PW

Procesy Proces wykonujący się program identyfikator PID Procesy spokrewnione proces macierzysty (rodzicielski, rodzic) identyfikator PPID proces potomny (potomek)

Grupy i sesje procesów Terminal sterujący Sesja procesów procesy związane z jednym terminalem sterującym identyfikator SID lider sesji Grupa procesów procesy współpracujące identyfikator PGID lider grupy grupa pierwszoplanowa grupy drugoplanowe Sesja Grupa P P P P P P

ps [opcje] Lista aktywnych procesów Opcje wyboru procesów -a -wszystkie procesy związane z jakimś terminalem sterującym -e, -A -wszystkie procesy -u user -wszystkie procesy wskazanego użytkownika -t term -wszystkie procesy związane z wskazanym przez argument term terminalem sterującym -p PID -proces o podanym numerze PID Opcje zakresu informacji -f -format pełny -l -format długi -j - format zorientowany na prace (SID, PGID) -o format -format zdefiniowany przez użytkownika

Przykład - lista procesów w systemie Solaris zawrat.apw16 $ ps -ef UID PID PPID C STIME TTY TIME CMD root 0 0 0 Apr 27? 0:32 sched root 1 0 0 Apr 27? 0:07 /etc/init - root 2 0 0 Apr 27? 0:05 pageout root 3 0 0 Apr 27? 222:55 fsflush root 276 1 0 Apr 27? 0:00 /usr/lib/saf/sac -t 300 root 242 1 0 Apr 27? 0:50 /usr/sbin/vold root 123 1 0 Apr 27? 0:01 /usr/sbin/rpcbind root 166 1 0 Apr 27? 0:00 /usr/lib/autofs/automountd root 208 1 0 Apr 27? 0:00 /usr/lib/lpsched root 160 1 0 Apr 27? 0:00 /usr/lib/nfs/lockd root 167 166 0 Apr 27? 93:25 /usr/lib/autofs/automountd root 283 280 0 Apr 27? 164:24 /usr/openwin/bin/x root 153 1 0 Apr 27? 2:37 /usr/sbin/inetd -s root 182 1 0 Apr 27? 3:06 /usr/sbin/syslogd root 186 1 0 Apr 27? 0:01 /usr/sbin/cron root 279 276 0 Apr 27? 0:00 /usr/lib/saf/ttymon root 251 1 0 Apr 27? 1:22 /usr/lib/sendmail -bd -q15m root 271 1 0 Apr 27? 0:22 /usr/local/ssh/sbin/sshd2 root 877 806 0 22:30:20 pts/1 0:00 ps -ef apw 806 803 0 21:59:42 pts/1 0:00 -zsh

Najważniejsze procesy systemowe Pierwszy proces w systemie PID=0 sched, swapper (UNIX, np. Solaris) demon wymiany INIT_TASK (Linux) proces idle Proces init PID=1 uruchamia usługi systemowe program /etc/init plik konfiguracyjny /etc/inittab adoptuje osierocone procesy

Najważniejsze procesy systemowe Demony oczekują w uśpieniu na żądanie określonej usługi nie posiadają terminala sterującego Przykłady demonów (Solaris) sched pageout fsflush syslogd lockd cron lpsched inetd -demon wymiany -demon wymiany stron -demon synchronizacji systemu plików -demon przechowywania komunikatów systemowych -demon zajmowania plików i rekordów -demon zegarowy -demon drukowania -demon internetowy

Reprezentacja procesu - UNIX (Solaris) Struktura procesu: struct proc { proc_t alokowana dynamicznie w przestrzeni adresowej jądra stale widoczna dla jądra Struktura użytkownika: struct user { user_t u-obszar, obszar użytkownika w przestrzeni adresowej użytkownika widoczna gdy proces się wykonuje (po przełączeniu kontekstu) zawiera dane potrzebne tylko w czasie wykonywania procesu

Reprezentacja procesu - UNIX (Solaris) Lista aktywnych procesów: extern proc_t *practive practive PID PID PID next prev next prev next prev

Reprezentacja procesu - Linux Struktura procesu: struct task_struct { alokowana dynamicznie w przestrzeni adresowej jądra Lista procesów init_task task_struct task_struct task_struct PID PID PID next prev next prev next prev

Reprezentacja procesu - Linux Tablica haszowania

Atrybuty procesu Stan procesu Powiązania z innymi procesami wskaźniki do sąsiednich procesów na liście wskaźniki do procesu macierzystego i rodzeństwa Identyfikatory Parametry szeregowania Atrybuty związane z systemem plików Parametry pamięci wirtualnej procesu Odmierzanie czasu Obsługa sygnałów Kontekst poziomu rejestru

Stany procesu - UNIX SVR4 Wykonywany w trybie użytkownika funkcja systemowa przerwanie powrót Wykonywany w trybie jądra zakończenie oczekiwanie na zdarzenie Zombie wywłaszczenie przydział procesora utworzenie procesu Utworzony przydział zasobów Gotowy wystąpienie zdarzenia Uśpiony wstrzymanie wznowienie wstrzymanie wznowienie Zatrzymany wznowienie Zatrzymany uśpiony

Stany procesu - Solaris SIDL SRUN SONPROC SSLEEP SZOMB SSTOPPED -pośredni w tworzeniu procesu -gotowy -wykonywany -uśpiony -zombie -zatrzymany

Stany procesu - Linux TASK_RUNNING -działający TASK_INTERRUPTIBLE -uśpiony przerywalny TASK_UNINTERRUPTIBLE -uśpiony nieprzerywalny TASK_ZOMBIE -zombie TASK_STOPPED -zatrzymany

Identyfikatory Identyfikatory procesów pid -identyfikator procesu ppid -identyfikator procesu macierzystego pgid -identyfikator grupy procesów sid -identyfikator sesji Identyfikatory użytkownika i grupy użytkowników uid, gid -identyfikatory rzeczywiste euid, egid -identyfikatory obowiązujące suid, sgid -identyfikatory zapamiętane

Informacje dotyczące systemu plików Tablica deskryptorów otwartych plików Maska uprawnień do tworzonych plików umask Wskaźnik do v-węzła katalogu głównego (korzeniowego) procesu Wskaźnik do v-węzła katalogu bieżącego procesu

Kontekst procesu Kontekst poziomu użytkownika obszar kodu wykonywalnego obszar danych obszar stosu obszary pamięci dzielonej Kontekst poziomu rejestru licznik rozkazów rejestr stanu procesora rejestry ogólnego przeznaczenia Kontekst poziomu jądra struktury danych opisujące proces stos jądra

Operacje na procesach Pobieranie i ustawianie atrybutów Tworzenie procesu Kończenie procesu Oczekiwanie na zakończenie procesu potomnego Uruchamianie programów

Funkcja main() int main (int argc, char *argv[], char *envp[]); Środowisko tablica napisów: argument wywołania: zmienna globalna: funkcje: zmienna=wartość char *envp[] extern char *environ[]; getenv(), putenv()

Pobieranie identyfikatorów pid_t getpid(void); pid_t getppid(void); pid_t getpgrp(void); pid_t getpgid(pid_t pid); uid_t getuid(void); gid_t getgid(void); uid_t geteuid(void); gid_t getegid(void);

Pobieranie i ustawianie atrybutów int setuid(uid_t uid); int setegid(gid_t egid); int seteuid(uid_t euid); int setgid(gid_t gid); Użytkownik root może ustawić dowolne wartości UID, EUID, SUID Zwykły użytkownik może zmieniać tylko EUID pomiędzy wartościami UID i SUID Modyfikatory praw dostępu w atrybutach pliku z kodem programu

Tworzenie procesu pid_t fork(void); pid_t vfork(void); Wartość zwracana przez funkcję: -1 błąd funkcji PID potomka w procesie macierzystym 0 w procesie potomnym

Funkcja fork() fork() a vfork() tworzy logiczną kopię kontekstu procesu macierzystego segment kodu współdzielony kopiowanie przy zapisie (ang. copy-on-write) nie wstrzymuje procesu macierzystego Funkcja vfork() nie tworzy kopii kontekstu procesu macierzystego (procesy współdzielą przestrzeń adresową) wstrzymuje proces macierzysty do momentu, gdy: potomek wywoła kod nowego programu (funkcja exec()) potomek zakończy się (funkcja exit())

Kończenie procesu void _exit(int status); void exit(int status); Realizacja przez jądro: zamyka otwarte pliki zwalnia przydzielone zasoby zmienia stan procesu na zombie zapisuje w strukturze procesu kod wyjścia (status zakończenie) sumaryczny czas wykonywania procesu i jego potomków procesy potomne adoptowane są przez proces init informuje proces macierzysty o zakończeniu potomka (sygnałem SIGCHLD)

Przykład tworzenie procesu (1) #include <stdio.h> #include <unistd.h> #include <sys/types.h> int main(void) { pid_t pid; if ((pid = fork()) == -1) { perror("fork"); exit(1);

Przykład tworzenie procesu (2) if (pid == 0) { printf("proces potomny: fork()=%d\n", pid); pid = getpid(); printf("potomek: PID = %d\n", pid); exit(0); else { printf("proces macierzysty: fork()=%d\n", pid); pid = getpid(); printf("rodzic: PID = %d\n", pid); exit(0); return(0);

Przykład tworzenie kilku procesów (1) #include <stdio.h> #include <stdlib.h> int main() { int n; printf ("PID=%d RODZIC \n", getpid()); for (n=0;n<3;n++) { if (fork()==0) printf ("PID=%d NOWY\n", getpid()); fflush(stdout); printf ("PID=%d KONIEC\n", getpid());

Przykład tworzenie kilku procesów (2) #include <stdio.h> #include <stdlib.h> int main() { int n; printf ("PID=%d RODZIC \n", getpid()); for (n=0;n<3;n++) { if (fork()==0) { printf ("PID=%d NOWY\n", getpid()); fflush(stdout); exit(0); printf ("PID=%d KONIEC\n", getpid());

Oczekiwanie na zakończenie procesu pid_t wait(int *status); pid_t waitpid(pid_t pid, int *status, int flags); pid_t wait3(int *status, int options, struct rusage *rusage); pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage);

Oczekiwanie na zakończenie procesu Realizacja przez jądro: nie ma żadnego procesu potomnego zwraca błąd nie ma potomka w stanie zombie usypia proces macierzysty, który oczekuje na sygnał śmierci potomka SIGCHLD jest potomek w stanie zombie dodaje czas procesora zużyty przez potomka w strukturze procesu macierzystego zwalnia strukturę procesu potomnego zwraca identyfikator PID jako wartość funkcji oraz status zakończenia procesu potomnego

Status zakończenia procesu Status zakończenia = kod wyjścia (liczba 2-bajtowa) proces zakończony normalnie, przez wywołanie exit() Kod zwrócony przez exit() 0 15 8 7 0 proces zakończony sygnałem 0 Numer sygnału 15 8 7 0 proces zatrzymany sygnałem Numer sygnału WSTOPFLG 15 8 7 0

Status zakończenia procesu c.d. Odczytanie statusu zakończenia while ((pid = wait(&status)) > 0) printf("pid=%d, status=%d\n", pid, (status>>8)); Makra WIFEXITED(status) WEXITSTATUS(status) WIFSIGNALED(status) WTERMSIG(status) WIFSTOPPED(status) WSTOPSIG(status)

Wykorzystanie zasobów Funkcje wait3() i wait4() Funkcja getrusage int getrusage(int who, struct rusage *r_usage); argument who RUSAGE_SELF -przez proces RUSAGE_CHILDREN -przez zakończone i oczekujące procesy potomne

Wykorzystanie zasobów struct rusage { struct timeval ru_utime; /* user time used */ struct timeval ru_stime; /* system time used */ long ru_maxrss; long ru_ixrss; long ru_idrss; long ru_isrss; long ru_minflt; long ru_majflt; long ru_nswap; long ru_inblock; long ru_oublock; long ru_msgsnd; long ru_msgrcv; long ru_nsignals; long ru_nvcsw; long ru_nivcsw;

Wykorzystanie zasobów struct timeval { time_t tv_sec; /* seconds */ suseconds_t tv_usec; /* microseconds */ ;

Przykład wykorzystanie zasobów (1) #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/resource.h> #include <sys/time.h> int main(void) { pid_t pid; int status; struct rusage rusage; unsigned long czas1, czas2; long suma, i; if ((pid = fork()) == -1) { perror("blad fork"); exit(1);

Przykład wykorzystanie zasobów (2) if (pid == 0) { pid = getpid(); printf("proces potomny: PID = %d\n", pid); for (i=0; i<40000; i++) { suma+=i*3+5; pid = getpid(); exit(0);

Przykład wykorzystanie zasobów (3) else { pid = getpid(); printf("proces macierzysty: PID = %d\n", pid); if (wait3(&status, 0, &rusage) == -1) { perror("blad wait3"); exit(1); czas1 = (rusage.ru_utime).tv_sec*1000 + (rusage.ru_utime).tv_usec/1000; czas2 = (rusage.ru_stime).tv_sec*1000 + (rusage.ru_stime).tv_usec/1000; printf("czas wykonania potomka\n"); printf("\t- w trybie użytkownika: %ld ms\n", czas1); printf("\t- w trybie jądra: %ld ms\n", czas2); exit(0); return(0);

Uruchamianie programów int execve(const char *path, char *const argv[], char *const envp[]); Realizacja: odszukuje i-węzła pliku z programem wykonywalnym sprawdza możliwości uruchomienia kopiuje argumenty wywołania i środowisko rozpoznaje format pliku wykonywalnego usuwa poprzedni kontekst procesu (zwalnia segmenty pamięci kodu, danych i stosu) łąduje kod nowego programu uruchamia nowy program (wznawia wykonywania bieżącego procesu)

Charakterystyka rodziny funkcji exec() Funkcja Przekazywanie argumentów Przekazywanie zmiennych środowiska Wskazanie położenia programu execv tablica zmienna globalna environ nazwa ścieżkowa pliku execve tablica tablica nazwa ścieżkowa pliku execvp tablica zmienna globalna environ ścieżka poszukiwań PATH execl lista zmienna globalna environ nazwa ścieżkowa pliku execle lista tablica nazwa ścieżkowa pliku execlp lista zmienna globalna environ ścieżka poszukiwań PATH

Przykład nowy program #include <stdio.h> #include <unistd.h> #include <sys/types.h> int main(void) { pid_t pid; pid = getpid(); printf("proces: PID = %d\n", pid); execlp("ps", "ps", "-f", NULL); printf("proces: PID = %d wykonal exec...\n", pid); exit(0);

Schemat uruchamiania programów potomek fork() rodzic exec(program) program _exit() wait()

Funkcja biblioteczna system() int system(const char *string); potomek vfork() rodzic exec( /bin/sh, ) sh c string _exit() wait()

Interpreter poleceń Interfejs tekstowy użytkownika powłoka (ang. shell) sh, csh, tcsh, zsh, bash Działanie interpretera podstawia wartości zmiennych i wyniki zagnieżdżonych poleceń dokonuje podziału na nazwę polecenia i argumenty (interpretacja separatorów) wykonuje przekierowanie strumieni danych, rozwija nazwy plików, rozpoznaje i wykonuje polecenie polecenie wbudowane lub funkcja program lub skrypt -> fork() + exec()

Uproszczony przykład z laboratorium L0 int main() { char bufor[80]; char* arg[10]; int bg; while (1) { printf("msh $ "); fgets(bufor, 80, stdin); bg = AnalizujPolecenie(bufor, arg); if (arg[0] == NULL) continue; else if (strcmp(arg[0], "exit")==0) exit(0); else Drukuj(arg); Wykonaj(arg, bg);

Uproszczony przykład z laboratorium L0 int AnalizujPolecenie(char *bufor, char *arg[]) { int counter=0; int i=0, j=0; arg[0] = bufor; arg[1] = NULL; /* Tu nalezy podzielic string wejsciowy na nazwe polecenia i poszczegolne argumenty oraz wypelnic tablice argumentow: arg[0] = nazwa, arg[1] = 1 argument, itd. */ return 0; int Drukuj(char *arg[]) { /* Tu nalezy wypisac nazwe polecenia i wszystkie argumenty na standardowe wyjscie (stdout) */

Uproszczony przykład z laboratorium L0 int Wykonaj(char **arg) { pid_t pid; int status; int i=0, n=0; char cmd[80]; while (arg[i]!= NULL){ strcat(cmd, arg[i++]); strcat(cmd, " "); system(cmd);

Schemat działania powłoki potomek fork() rodzic exec(program) program _exit() wait() potomek na pierwszym planie potomek w tle

Przykład prosty interpreter poleceń int main() { char bufor[80]; char* arg[10]; int bg; while (1) { printf("msh $ "); fgets(bufor, 80, stdin); bg = AnalizujPolecenie(bufor, arg); if (arg[0] == NULL) continue; else if (strcmp(arg[0], "exit")==0) exit(0); else Wykonaj(arg, bg);

Przykład prosty interpreter poleceń int Wykonaj(char **arg, int bg) { pid_t pid; int status; if ((pid = fork()) == 0) { execvp(arg[0],arg); perror("blad exec"); exit(1); else if (pid > 0) { if (bg == 0) waitpid(pid, &stat, 0); return 0; else { perror("blad fork"); exit(2);

Przykład prosty interpreter poleceń int AnalizujPolecenie(char *bufor, char *arg[]) { int counter=0; int i=0, j=0; while (bufor[counter]!= '\n') { while (bufor[counter] == ' ' bufor[counter] == '\t') counter++; if (bufor[counter]!= '\n') { arg[i++] = &bufor[counter]; while (bufor[counter]!= ' ' && bufor[counter]!= '\t' && bufor[counter]!= '\n') counter++; if (bufor[counter]!= '\n') bufor[counter++] = '\0';

Przykład prosty interpreter poleceń bufor[counter] = '\0'; arg[i]=null; if (i>0) while (arg[i-1][j]!= '\0') { if (arg[i-1][j] == '&') { if (j == 0) arg[i-1] = NULL; else arg[i-1][j] = '\0'; return 1; j++; return 0;