Управление на процеси

24
Системно програмиране, М. Филипова Управление на процеси гл. ас. Моника Филипова ФМИ, Катедра Изчислителни системи

Upload: candice-austin

Post on 15-Mar-2016

72 views

Category:

Documents


2 download

DESCRIPTION

Управление на процеси. гл. ас. Моника Филипова ФМИ, Катедра Изчислителни системи. Съдържание. Контекст на процес и променливи на обкръжението Създаване на процес - fork Завършване на процес - exit и _exit Системни примитиви wait Функции на системния примитив exec - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Управление на процеси

Системно програмиране, М. Филипова 1

Управление на процеси

гл. ас. Моника ФилиповаФМИ, Катедра Изчислителни системи

Page 2: Управление на процеси

Системно програмиране, М. Филипова 2

Съдържание

Контекст на процес и променливи на обкръжението Създаване на процес - fork Завършване на процес - exit и _exit Системни примитиви wait Функции на системния примитив exec Потребителски идентификатори на процес Групи процеси Сесия Управление на заданията

Page 3: Управление на процеси

Системно програмиране, М. Филипова 3

Контекст на процес и променливи на обкръжението

Предаване на аргументи към функция mainint main(int argc, char *argv[]);

argc - брой на аргументитеargv - масив от указатели към самите аргументи

Аргументи към main се предават чрез аргументите на примитива exec.

Наричаме ги аргументи от командния ред (command line arguments) заради програмата shell.

Page 4: Управление на процеси

Системно програмиране, М. Филипова 4

Променливи на обкръжението

extern char **environ; Указател към променливите на обкръжението на процеса. Всеки указател сочи към символен низ, който има вида: name=value

#include <stdlib.h>char *getenv(const char *name);

Връща указател към value, NULL при грешка.int putenv(const char *str);int setenv(const char *name,

const char *value, int rewrite);Връщат 0 при успех, -1 при грешка.

void unsetenv(const char *name);

Page 5: Управление на процеси

Системно програмиране, М. Филипова 5

Пример. Извежда на стандартния изход аргументите от командния ред и променливите на обкръжението.

#include "ourhdr.h"

main(int argc, char *argv[]){ int i; char **ptr; extern char **environ; for (i=0; i<argc; i++) /* echo command line arguments */ printf("arg[%d]: %s\n", i, argv[i]);

for (ptr = environ; *ptr != 0; ptr++) /* echo environment strings */ printf("%s\n", *ptr); printf("\n"); exit(0);}

Page 6: Управление на процеси

Системно програмиране, М. Филипова 6

Резултат от изпълнение на програмата

$ a.out argument1 xxxx thirdarg[0]: a.outarg[1]: argument1arg[2]: xxxxarg[3]: thirdHOME=/home/moniSHELL=/bin/bashPS1=[\u@\h \W]\$ USER=moni. . .

Page 7: Управление на процеси

Системно програмиране, М. Филипова 7

Атрибути на процес идентификатор на процеса (pid) идентификатор на процеса-баща (ppid от parent pid) идентификатор на група процеси (pgid) идентификатор на сесия (sid) реален потребителски идентификатор (ruid) ефективен потребителски идентификатор (euid) реален идентификатор на потребителска група (rgid) ефективен идентификатор на потребителска група (egid) файлови дескриптори на отворените файлове текущ каталог управляващ терминал маска, използвана при създаване на файлове (заредена с примитива

umask) реакция на процеса при получаване на различни сигнали времена за изпълнение на процеса в системна и потребителска фаза

(system and user CPU time)

Page 8: Управление на процеси

Системно програмиране, М. Филипова 8

Създаване на процес - fork#include <sys/types.h>pid_t fork(void);

В процеса-баща връща pid на процеса-син или -1 при грешка.В процеса-син връща 0.

Общото между процесите баща и син идентификатор на група процеси идентификатор на сесия реален потребителски идентификатор ефективен потребителски идентификатор реален идентификатор на потребителска група ефективен идентификатор на потребителска група файлови дескриптори на отворените файлове текущ каталог управляващ терминал маска, използвана при създаване на файлове реакция на процеса при получаване на различни сигнали променливи от обкръжението

Page 9: Управление на процеси

Системно програмиране, М. Филипова 9

Пример. Наследяване на отворените файлове в процес-син#include "ourhdr.h"int glob = 5;char buf[] = "write to standard output\n";main(void){ int local; pid_t pid; local = 77; if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1) err_sys_exit("write error"); printf("before fork\n"); /* we do not flush stdout before fork */ if ( (pid = fork()) < 0) err_sys_exit("fork error"); else if (pid == 0) { /* in child process */ glob++; local++; } else sleep(3); /* in parent process *//* in parent and child*/ printf("pid = %d, glob = %d, local = %d\n", getpid(), glob, local); exit(0);}

Page 10: Управление на процеси

Системно програмиране, М. Филипова 10

Резултат от изпълнение на програмата

$ a.outwrite to standard outputbefore forkpid = 1840, glob = 6, local = 78pid = 1839, glob = 5, local = 77$ a.out > out$ cat outwrite to standard outputbefore forkpid = 1842, glob = 6, local = 78before forkpid = 1841, glob = 5, local = 77

Page 11: Управление на процеси

Системно програмиране, М. Филипова 11

Завършване на процес - exit и _exit Нормално завършване

извикване на exit или _exit изпълнение на return от функцията main

Аварийно завършване получаване на сигнал, за който реакцията на процеса е завършване извикване на функцията abort (сигнал SIGABRT)

#include <unistd.h>void _exit(int status);#include <stdlib.h>void exit(int status);#include <stdlib.h>int atexit(void (*fucntion)(void));

Връща 0 при успех, -1 при грешка.

Page 12: Управление на процеси

Системно програмиране, М. Филипова 12

Системни примитиви wait#include <sys/types.h>#include <sys/wait.h>pid_t wait(int *status);pid_t waitpid(pid_t pid, int *status,

int options); Чака завършването на определен син.pid == -1 първия син, който завършиpid > 0 син с идентификатор pidpid == 0 първия син от същата група процесиpid < -1 първия син от група процеси с идентификатор |pid| Ако options е WNOHANG, процесът не се блокира ако

синът не е завършил, а функцията връща 0.При успех функциите връщат pid на завършилия син, а чрез аргумента status кода му на завършване.

Page 13: Управление на процеси

Системно програмиране, М. Филипова 13

Макроси за проверка на status

Макроси ОписаниеWIFEXITED(status) WEXITSTATUS(status)

Връща истина ако процесът-син е завършил нормално. Връща кода на завършване.

WIFSIGNALED(status)

WTERMSIG(status)WCOREDUMP(status)

Връща истина ако процесът-син е завършил аварийно.Връща номера на сигнала.Връща истина ако е създаден файл core.

WIFSTOPPED(status)

WSTOPSIG(status)

Връща истина ако процесът-син е в състояние stopped. Връща номера на сигнала.

Page 14: Управление на процеси

Системно програмиране, М. Филипова 14

Функции на системния примитив execint execl(const char *name, const char *arg0

[, const char *arg1]..., 0);int execlp(const char *name, const char *arg0

[, const char *arg1]..., 0);int execv(const char *name, char *argv[]);int execvp(const char *name, char *argv[]);int execle(const char *name, const char *arg0

[, const char *arg1]..., 0, char *envp[]);int execve(const char *name, char *argv[],

char *envp[]);name - име на файл, съдържащ програма в изпълним кодarg0, arg1, ... или argv[]- указатели към аргументите, които ще бъдат

предадени на функцията main на новата програмаenvp[] - указатели към символни низове, съдържащи променливите от

обкръжението на процеса

Връщат -1 при грешка, нищо при успех.

Page 15: Управление на процеси

Системно програмиране, М. Филипова 15

При exec се променя образа на процеса променливите от обкръжението (при execle или

execve с аргумент envp) ефективния потребителски идентификатор (ако е

вдигнат set-UID бита за файла с име name) ефективния идентификатор на потребителска група

(ако е вдигнат set-GID бита за файла с име name) файлови дескриптори на отворените файлове

(затварят се тези с вдигнат флаг FD_CLOEXEC) реакция на процеса при получаване на сигнали (за

сигналите, за които реакцията е потребителска функция)

Page 16: Управление на процеси

Системно програмиране, М. Филипова 16

#include "ourhdr.h"main(void){ int status; pid_t pid;

pid = fork(); if (pid == 0) { /* in child process */ execl("/bin/ls", "ls", "-l", 0); err_sys_exit("exec ls error"); } else /* in parent process */ if (pid < 0) err_sys_exit("fork error"); else { wait(&status); printf("Parent after end of child: status=%d\n", status); } exit(0);}

Пример. Създаване на процес и изпълнение на програма

Page 17: Управление на процеси

Системно програмиране, М. Филипова 17

#include "ourhdr.h"main(void){ int status, fd; pid_t pid; pid = fork(); if (pid == 0) { /* in child process */ if (( fd=open("outfile", O_WRONLY|O_CREAT|O_TRUNC, 0640)) == -1) err_sys_exit("create outfile error"); close(1); dup(fd); close(fd); execl("/bin/ls", "ls", "-l", 0); err_sys_exit("exec ls error"); } else /* in parent process */ if (pid < 0) err_sys_exit("fork error"); else { wait(&status); printf("Parent after end of child: status=%d\n", status); } exit(0);}

Пример. Пренасочване на стандартния изход

Page 18: Управление на процеси

Системно програмиране, М. Филипова 18

Потребителски идентификатори на процес реален потребителски идентификатор - ruid ефективен потребителски идентификатор - euid реален идентификатор на потребителска група - rgid ефективен идентификатор на потребителска група – egid съхранен uid - suid При fork процес-син наследява потребителските

идентификатори от бащата.

uid_t getuid(void); Връща ruid на процеса.uid_t geteuid(void); Връща euid на процеса.gid_t getgid(void); Връща rgid на процеса.gid_t getegid(void);Връща egid на процеса.

Page 19: Управление на процеси

Системно програмиране, М. Филипова 19

Изменение на потребителски идентификатори

При изпълнение на set-UID програмата (при exec) set-UID програма - в кода на защита на файла с изпълнимия

код битът "изменение на UID при изпълнение" е 1 (04000).– Сменя се euid и suid на процеса със собственика на файла с

изпълнимия код.

int setuid(uid_t uid);– Ако текущият euid на процеса е 0, то се променя euid, ruid и

suid с аргумента uid.– Ако текущият euid на процеса не е 0, то се променя euid с

аргумента uid, само ако uid е равен на ruid или на suid.Връща 0 при успех, -1 при грешка.

Page 20: Управление на процеси

Системно програмиране, М. Филипова 20

Групи процеси Всеки процес принадлежи на група от процеси, която

включва един или повече процеса. Всяка група има лидер на групата (group leader) - процесът,

създал групата. Групата се идентифицира чрез идентификатор на група

процеси (process group ID или PGID) - pid на процеса-лидер на групата.

При fork процес-син наследява групата от бащата. При exec груповият идентификатор не се променя.pid_t getpgrp(void);pid_t getpgid(pid_t pid);

Връща идентификатор на група при успех, -1 при грешка.

int setpgrp(void);int setpgid(pid_t pid, pid_t pgid);

Връщат 0 при успех, -1 при грешка.

Page 21: Управление на процеси

Системно програмиране, М. Филипова 21

Сесия Сесията включва една или повече групи процеси. Всяка сесия има лидер на сесия - процесът, създал сесията. Сесията се идентифицира чрез идентификатор на сесия (session ID или

SID) - pid на процеса-лидер на сесията. При fork процес-син наследява идентификатора на сесия от бащата. При exec идентификатора на сесия не се променя. При exit на процес-лидер на сесия с управляващ терминал, се прекъсва

връзката между сесията и терминала.

pid_t getsid(pid_t pid);Връща идентификатор на сесия при успех, -1 при грешка.

pid_t setsid(void);Връща идентификатор на сесия при успех, -1 при грешка.

– Създава нова сесия ако процесът, изпълняващ примитива, преди това не е лидер на група.

– Процесът става лидер на новата сесия, лидер на първата група в тази сесия и няма управляващ терминал.

Page 22: Управление на процеси

Системно програмиране, М. Филипова 22

Пример. Наследяване на сесия и създаване на нова сесия#include "ourhdr.h"main(void){ int pid, status; printf("Parent: pid=%d, grp=%d, sid=%d\n", getpid(), getpgrp(), getsid(0)); if ((pid = fork()) < 0) err_sys_exit("fork error"); else if (pid == 0) { /* in child process */ printf("Child: pid=%d, grp=%d, sid=%d\n", getpid(), getpgrp(), getsid(0)); /* child become session and group leader without tty */ if (setsid() == -1) err_sys_exit("setsid error"); printf("Child after setsid: pid=%d, grp=%d, sid=%d\n", getpid(), getpgrp(), getsid(0)); system("ps xj"); exit(0); } wait(&status); exit(0); /* in parent process */}

Page 23: Управление на процеси

Системно програмиране, М. Филипова 23

Резултат от изпълнение на програмата

$ a.outParent: pid=16261, grp=16261, sid=12467Child: pid=16262, grp=16261, sid=12467Child after setsid: pid=16262, grp=16262, sid=16262 PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 2535 12467 12467 12467 tty1 16261 Ss 501 0:00 -bash12467 16261 16261 12467 tty1 16261 S+ 501 0:00 a.out16261 16262 16262 16262 ? -1 Ss 501 0:00 a.out16262 16263 16262 16262 ? -1 R 501 0:00 ps xj

Page 24: Управление на процеси

Системно програмиране, М. Филипова 24

Управление на заданията Понятието задание се реализира от командния интерпретатор

като се използват групи процеси (job control shell). Заданието е един или повече процеса, които са в една група. Процесът login-shell е лидер на сесия с управляващ терминал. Всички процеси пораждани от login-shell процеса са

организирани като задания (групи): една е привилегирована (foreground) и всички други - фонови групи (background).

$ find /home -name core -print > outfind 2>&1 &$ ps axj | more

find pid=3124

bash pid=3106

ps pid=3126

more pid=3127

Сесия 3106

Група 3124 Група 3106 Група 3126