Similar presentations:
Многопоточное программирование (лекция 4). Создание процессов, copy-on-write, атрибуты процесса, ожидание потомка
1. Многопоточное программирование
Лекция №4Многопоточное
программирование
Дмитрий Калугин-Балашов
2. Создание процессов
pid_t fork();2
3. Создание процессов
pid_t fork();pid_t vfork();
3
4. Создание процессов
pid_t fork();pid_t vfork();
pid_t forkpty(int *amaster,
char *name,
const struct termios *termp,
const struct winsize *winp);
4
5. Copy-on-write
56. Copy-on-write
76
5
4
3
2
1
0
6
7. Copy-on-write
76
5
4
3
2
1
2
0
1
0
7
8. Copy-on-write
76
5
7
6
5
4
4
3
3
2
2
1
1
0
0
8
9. Copy-on-write
fork()7
6
7
7
6
6
5
5
4
4
4
3
3
3
2
2
2
1
1
1
0
0
0
5
9
10. Copy-on-write
fork()7
6
7
7
6
6
5
5
4
4
4
3
3
3
2
2
2
1
1
1
0
0
0
5
1
0
11. Copy-on-write
fork()7
6
?
7
7
6
6
5
5
4
4
4
3
3
3
2
2
2
1
1
1
0
0
0
5
1
1
12. Copy-on-write
fork()8
?
7
7
6
6
6
5
5
5
4
4
4
3
3
3
2
2
2
1
1
1
0
0
0
7
1
2
13. Copy-on-write
fork()8
7
7
7
6
6
6
5
5
5
4
4
4
3
3
3
2
2
2
1
1
1
0
0
0
1
3
14. Дерево процессов
init1
4
15. Атрибуты процесса
PID и PPID (Parent PID).1.
2.
pid_t getpid();
pid_t getppid();
1
5
16. Атрибуты процесса
PID и PPID (Parent PID).1.
2.
pid_t getpid();
pid_t getppid();
3.
// PID=1 для init.
4.
5.
// Если родительский процесс завершается,
// потомок получает PPID=1.
1
6
17. Атрибуты процесса
UID, GID, EUID, EGID.1. // “Кто создал?”
2. // (Реальные идентификаторы пользователя и группы).
3.
4.
5.
6.
uid_t getuid();
int setuid(uid_t uid);
gid_t getgid();
int setgid(gid_t gid);
7. // “От чьего лица выполняется?”
8. // (Эффективные идентификаторы пользователя и группы).
9.
10.
11.
12.
uid_t geteuid();
int seteuid(uid_t uid);
gid_t getegid();
int setegid(gid_t gid);
1
7
18. Атрибуты процесса
Корневой каталог.1. int chroot(const char *path);
2. // --- /var/new_root/somefile.txt
3. // --- chroot(“/var/new_root”);
4. // --- /somefile.txt
1
8
19. Атрибуты процесса
Рабочий каталог.1. int chdir(const char *path);
2. int fchdir(int fd);
1
9
20. Атрибуты процесса
Приоритет.1. int nice(int incr);
2. // NZERO = 20
3. // NICE = 0..39
4. // NICE-20
2
0
21. Атрибуты процесса
Ограничения.1. int getrlimit(int resource, struct rlimit *rlp);
2. int setrlimit(int resource, const struct rlimit *rlp);
3. struct rlimit {
4.
rlim_t rlim_cur;
5.
rlim_t rlim_max;
6. }
7. // RLIMIT_CORE, RLIMIT_CPU, RLIMIT_DATA, RLIMIT_FSIZE,
RLIMIT_NOFILE, RLIMIT_STACK, RLIMIT_AS
8. // RLIM_SAVED_MAX, RLIM_SAVED_CUR, RLIM_INFINITY
2
1
22. Атрибуты процесса
Ограничения.1. long ulimit(int cmd, …); // Устаревший
2. int getrusage(int who, struct rusage *r_usage);
3. // RUSAGE_SELF, RUSAGE_CHILDREN
4. int prlimit(pid_t pid,
5.
int resource,
6.
const struct rlimit *new_limit,
7.
struct rlimit *old_limit);
2
2
23. Атрибуты процесса
Переменные окружения.1.
2.
3.
4.
5.
6.
extern char **environ;
// Имя=Значение
// Имя=Значение
// ...
// Имя=Значение
// \0
7.
8.
9.
10.
char *getenv(const char *var);
int putenv(char *string);
int setenv(const char *var, const char *val, int overwrite);
int unsetenv(const char *var);
2
3
24. Порождение процесов
Порождение процесса через exec.-
int execl(const char *path, const char *arg, ...);
int execv(const char *path, char *const argv[]);
int execle(const char *path, const char *arg, ..., char * const
envp[]);
int execve(const char *path, char *const argv[], char *const
envp[]);
int execlp(const char *file, const char *arg, ...);
int execvp(const char *file, char *const argv[]);
2
4
25. Порождение процесов
Порождение процесса через exec.-
int execl(const char *path, const char *arg, ...);
int execv(const char *path, char *const argv[]);
int execle(const char *path, const char *arg, ..., char * const
envp[]);
int execve(const char *path, char *const argv[], char *const
envp[]);
int execlp(const char *file, const char *arg, ...);
int execvp(const char *file, char *const argv[]);
2
5
26. Порождение процесов
Порождение процесса через exec.-
int execl(const char *path, const char *arg, ...);
int execv(const char *path, char *const argv[]);
int execle(const char *path, const char *arg, ..., char * const
envp[]);
int execve(const char *path, char *const argv[], char *const
envp[]);
int execlp(const char *file, const char *arg, ...);
int execvp(const char *file, char *const argv[]);
2
6
27. Порождение процесов
Порождение процесса через exec.-
int execl(const char *path, const char *arg, ...);
int execv(const char *path, char *const argv[]);
int execle(const char *path, const char *arg, ..., char * const
envp[]);
int execve(const char *path, char *const argv[], char *const
envp[]);
int execlp(const char *file, const char *arg, ...);
int execvp(const char *file, char *const argv[]);
2
7
28. Порождение процесов
Порождение процесса через exec.-
int execl(const char *path, const char *arg, ...);
int execv(const char *path, char *const argv[]);
int execle(const char *path, const char *arg, ..., char * const
envp[]);
int execve(const char *path, char *const argv[], char *const
envp[]);
int execlp(const char *file, const char *arg, ...);
int execvp(const char *file, char *const argv[]);
2
8
29. Порождение процесов
Порождение процесса через system.int system(const char *command);
2
9
30. Ожидание потомка
Как предотвратить зомби?1. pid_t waitpid(pid_t pid, int *statusp, int options);
2. // pid <- PID или -1
3. // options <- WNOHANG
4. // wait(&status) = waitpid(-1, &status, 0);
3
0
31. Исполнение процесса
Рождение3
1
32. Исполнение процесса
РождениеГотовность
3
2
33. Исполнение процесса
РождениеГотовность
Выполнение
Ожидание
3
3
34. Исполнение процесса
РождениеГотовность
Выполнение
Смерть
Ожидание
3
4
35. Сигналы
read(…)3
5
36. Сигналы
SIGNALread(…)
3
6
37. Сигналы
SIGNALread(…)
errno = EINTR
3
7
38. Сигналы
Основые типы сигналов.1. kill –l
2.
3.
4.
5.
6.
7.
8.
9.
10.
SIGABRT
SIGALRM
SIGCHLD
SIGINT
SIGTERM
SIGKILL
SIGUSR1
SIGUSR2
SIGHUP
11. SIGRTMIN
12. SIGRTMAX
3
8
39. Сигналы
ANSI C.1. void handler(int signum)
2. {
3.
// ...
4. }
5.
6.
7.
8.
// ANSI C
signal(SIGUSR1, handler);
signal(SIGUSR2, SIG_IGN);
signal(SIGTERM, SIG_DFL);
3
9
40. Сигналы
POSIX.1. // POSIX
2. struct sigaction {
3.
void (*sa_handler)(int);
4.
void (*sa_sigaction)(int, siginfo_t *, void *);
5.
sigset_t sa_mask;
6.
int sa_flags;
7.
void (*sa_restorer)(void);
8. }
4
0
41. Сигналы
POSIX.1. // POSIX
2. struct sigaction {
3.
void (*sa_handler)(int);
4.
void (*sa_sigaction)(int, siginfo_t *, void *);
5.
sigset_t sa_mask;
6.
int sa_flags;
7.
void (*sa_restorer)(void);
8. }
4
1
42. Сигналы
POSIX.1. // POSIX
2. struct sigaction {
3.
void (*sa_handler)(int);
4.
void (*sa_sigaction)(int, siginfo_t *, void *);
5.
sigset_t sa_mask;
6.
int sa_flags;
7.
void (*sa_restorer)(void);
8. }
9.
10.
11.
12.
13.
int
int
int
int
int
sigemptyset(sigset_t *set);
sigfillset(sigset_t *set);
sigaddset(sigset_t *set, int signum);
sigdelset(sigset_t *set, int signum);
sigismember(const sigset_t *set, int signum);
4
2
43. Сигналы
POSIX.1. // POSIX
2. struct sigaction {
3.
void (*sa_handler)(int);
4.
void (*sa_sigaction)(int, siginfo_t *, void *);
5.
sigset_t sa_mask;
6.
int sa_flags; // SA_NODEFER, SA_RESETHAND, SA_SIGINFO,
7.
8.
SA_RESTART
void (*sa_restorer)(void);
}
9.
10.
11.
12.
13.
int
int
int
int
int
sigemptyset(sigset_t *set);
sigfillset(sigset_t *set);
sigaddset(sigset_t *set, int signum);
sigdelset(sigset_t *set, int signum);
sigismember(const sigset_t *set, int signum);
4
3
44. Сигналы
POSIX.1. // POSIX
2. struct sigaction {
3.
void (*sa_handler)(int);
4.
void (*sa_sigaction)(int, siginfo_t *, void *);
5.
sigset_t sa_mask;
6.
int sa_flags; // SA_NODEFER, SA_RESETHAND, SA_SIGINFO,
7.
8.
9.
10.
11.
12.
13.
14.
SA_RESTART
void (*sa_restorer)(void);
}
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum);
int sigismember(const sigset_t *set, int signum);
int sigaction(int signum, const struct sigaction *act, struct
sigaction *oldact);
4
4
45. Сигналы
siginfo_t.1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
union sigval {
int sival_int;
void *sival_ptr;
};
typedef struct {
int si_signo;
int si_code; /* SI_USER, SI_KERNEL, SI_QUEUE, SI_TIMER */
union sigval si_value;
int si_errno;
pid_t si_pid;
uid_t si_uid;
void *si_addr;
int si_status;
int si_band;
} siginfo_t;
4
5
46. Сигналы
Отправка и ожидание сигнала.1. int kill(pid_t pid, int signum);
2. int sigqueue(pid_t pid, int sig, const union sigval value);
3. int raise(int signum); // Синхронно.
4. int abort(); // SIGABRT
5. unsigned alarm(unsigned secs); // SIGALRM
6. int pause();
7. int sigwait(const sigset_t *set, int *signum);
4
6
47. Сигналы
Безопасность.1. volatile sig_atomic_t GlobalVariable;
4
7
48. Блокировка
File4
8
49. Блокировка
PIDPID
File
PID
PID
PID
4
9
50. Блокировка
PIDREAD
File
PID
PID
PID
WRITE
PID
5
0
51. Блокировка
PIDPID
Exclusive lock
File
PID
Exclusive lock
PID
PID
5
1
52. Блокировка
PIDPID
File
PID
PID
PID
5
2
53. Блокировка
PIDPID
File
PID
PID
PID
5
3
54. Блокировка
PIDPID
File
PID
PID
PID
5
4
55. Блокировка
PIDExclusive lock
File
PID
Exclusive lock
Exclusive lock
PID
Exclusive lock
PID
PID
5
5
56. Блокировка
PIDExclusive lock
File
PID
Exclusive lock
Exclusive lock
PID
Exclusive lock
PID
PID
5
6
57. Блокировка
PIDExclusive lock
File
PID
Exclusive lock
Exclusive lock
PID
Exclusive lock
PID
PID
5
7
58. Блокировка
PIDShared lock
File
PID
Shared lock
Shared lock
PID
Exclusive lock
PID
PID
5
8
59. Блокировка
Блокировки в коде.1. flock(fd, LOCK_EX);
2. flock(fd, LOCK_SH);
3. flock(fd, LOCK_UN);
4. flock(fd, LOCK_EX | LOCK_NB);
5. flock(fd, LOCK_SH | LOCK_NB);
5
9
60. Файлы блокировок
Что мы хотим?1.
2.
3.
4.
5.
6.
7.
8.
9.
if(lock(“filename”))
{
// Какие-то действия
unlock(“filename”);
}
else
{
// ...
}
6
0
61. Файлы блокировок
Реализация lock().1. bool lock(char *filename)
2. {
3.
int fd;
4.
if(fd = open(filename, O_WRONLY | O_CREATE | O_EXCL, 0))
== -1)
{
5.
6.
7.
8.
9.
10. }
return false;
}
close(fd);
return true;
6
1
62. Файлы блокировок
Реализация lock().1. bool lock(char *filename)
2. {
3.
int fd;
4.
if(fd = open(filename, O_WRONLY | O_CREATE | O_EXCL, 0))
== -1)
{
5.
6.
7.
8.
9.
10. }
return false;
}
close(fd);
return true;
6
2
63. Файлы блокировок
Реализация lock().1. bool lock(char *filename)
2. {
3.
int fd;
4.
if(fd = open(filename, O_WRONLY | O_CREATE | O_EXCL, 0))
== -1)
{
5.
6.
7.
8.
9.
10. }
return false;
}
close(fd);
return true;
6
3
64. Файлы блокировок
Реализация unlock().1. bool unlock(char *filename)
2. {
3.
unlink(filename);
4.
return true;
5. }
6
4
65. Общие смещения в файлах
Какой-то файл…6
5
66. Общие смещения в файлах
Процесс 1Какой-то файл…
6
6
67. Общие смещения в файлах
Процесс 1Какой-то файл…
6
7
68. Общие смещения в файлах
Процесс 1Какой-то файл…
6
8
69. Общие смещения в файлах
Процесс 1fd
Какой-то файл…
6
9
70. Общие смещения в файлах
Процесс 1fork()
fd
Процесс 2
fd
Какой-то файл…
7
0
71. Общие смещения в файлах
Процесс 1fork()
fd
Процесс 2
fd
Position
Какой-то файл…
7
1
72. Общие смещения в файлах
Процесс 1fork()
fd
Процесс 2
fd
Position
Какой-то файл…
7
2
73. Общие смещения в файлах
seek(fd, NUMBER, SEEK_SET);Процесс 1
fork()
fd
Процесс 2
fd
Position
Какой-то файл…
7
3
74. Общие смещения в файлах
seek(fd, NUMBER, SEEK_SET);Процесс 1
fork()
fd
lseek(fd, 0, SEEK_CUR);
Процесс 2
fd
Position
Какой-то файл…
7
4
75. Неименованные каналы
int pipe(int fd[2]);7
5
76. Неименованные каналы
fd[1]fd[0]
7
6
77. Неименованные каналы
fd[1]fd[0]
Канал
7
7
78. Неименованные каналы
fd[1]fd[0]
Канал
7
8
79. Неименованные каналы
fd[1]fd[0]
Канал
7
9
80. Неименованные каналы
fd[1]fd[0]
fd[1]
fd[0]
Канал
8
0
81. Неименованные каналы
fd[1]fd[0]
fd[1]
fd[0]
Канал
8
1
82. Неименованные каналы
fd[1]fd[0]
fd[1]
fd[0]
Канал
8
2
83. Неименованные каналы
fd[1]fd[0]
fd[1]
fd[0]
Канал
8
3
84. Неименованные каналы
fd[1]fd[0]
fd[1]
fd[0]
Канал
8
4
85. Неименованные каналы
Канал8
5
86. Неименованные каналы
PIPE_BUFКанал
8
6
87. Неименованные каналы
PIPE_BUFКанал
long v = fpathconf(pfd[0], _PC_PIPE_BUF);
8
7
88. Неименованные каналы
Пример конвейера.1.
who | sort | uniq | wc
8
8
89. Неименованные каналы
who stdoutstdin sort stdout
stdin uniq stdout
stdin wc
8
9
90. Неименованные каналы
who stdoutstdin sort stdout
stdin uniq stdout
stdin wc
9
0
91. Неименованные каналы
who stdoutstdin sort stdout
stdin uniq stdout
stdin wc
Канал 1
9
1
92. Неименованные каналы
who stdoutstdin sort stdout
Канал 1
stdin uniq stdout
stdin wc
Канал 2
9
2
93. Неименованные каналы
who stdoutstdin sort stdout
Канал 1
stdin uniq stdout
Канал 2
stdin wc
Канал 3
9
3
94. Неименованные каналы
Дублирование дескрипторов.1.
2.
3.
int dup(int oldfd);
int dup2(int oldfd, int newfd); // dup2(N, N) = N
int dup3(int oldfd, int newfd, int flags /* O_CLOEXEC */);
9
4
95. Неименованные каналы
Пример конвеера.1. void who_wc() {
2.
int pfd[2];
3.
pipe(pfd);
4.
if(!fork()) {
5.
close(STDOUT_FILENO);
6.
dup2(pfd[1], STDOUT_FILENO);
7.
close(pfd[0]); close(pfd[1]);
8.
execlp(“who”, “who”, NULL); }
9.
if(!fork()) {
10.
close(STDIN_FILENO);
11.
dup2(pfd[0], STDIN_FILENO);
12.
close(pfd[0]); close(pfd[1]);
13.
execlp(“wc”, “wc”, “-l”, NULL); }
14.
close(pfd[0]); close(pfd[1]);
15.
wait(NULL); wait(NULL);
16. }
9
5
96. Неименованные каналы
popen и pclose.1.
2.
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
9
6
97. Неименованные каналы
Двусторонние каналы.1. int socketpair(int d, /* AF_UNIX */
2.
int type,
3.
int protocol,
4.
int sv[2]);
9
7
98. Именованные каналы
FIFO.1. int mkfifo(const char *path,
2.
mode_t perms);
9
8
99.
Спасибо завнимание!
Дмитрий Калугин-Балашов
[email protected]