Многопоточное программирование
Создание процессов
Создание процессов
Создание процессов
Copy-on-write
Copy-on-write
Copy-on-write
Copy-on-write
Copy-on-write
Copy-on-write
Copy-on-write
Copy-on-write
Copy-on-write
Дерево процессов
Атрибуты процесса
Атрибуты процесса
Атрибуты процесса
Атрибуты процесса
Атрибуты процесса
Атрибуты процесса
Атрибуты процесса
Атрибуты процесса
Атрибуты процесса
Порождение процесов
Порождение процесов
Порождение процесов
Порождение процесов
Порождение процесов
Порождение процесов
Ожидание потомка
Исполнение процесса
Исполнение процесса
Исполнение процесса
Исполнение процесса
Сигналы
Сигналы
Сигналы
Сигналы
Сигналы
Сигналы
Сигналы
Сигналы
Сигналы
Сигналы
Сигналы
Сигналы
Сигналы
Блокировка
Блокировка
Блокировка
Блокировка
Блокировка
Блокировка
Блокировка
Блокировка
Блокировка
Блокировка
Блокировка
Блокировка
Файлы блокировок
Файлы блокировок
Файлы блокировок
Файлы блокировок
Файлы блокировок
Общие смещения в файлах
Общие смещения в файлах
Общие смещения в файлах
Общие смещения в файлах
Общие смещения в файлах
Общие смещения в файлах
Общие смещения в файлах
Общие смещения в файлах
Общие смещения в файлах
Общие смещения в файлах
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Неименованные каналы
Именованные каналы
408.92K
Category: programmingprogramming

Многопоточное программирование (лекция 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

5

6. Copy-on-write

7
6
5
4
3
2
1
0
6

7. Copy-on-write

7
6
5
4
3
2
1
2
0
1
0
7

8. Copy-on-write

7
6
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. Дерево процессов

init
1
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. Сигналы

SIGNAL
read(…)
3
6

37. Сигналы

SIGNAL
read(…)
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. Блокировка

File
4
8

49. Блокировка

PID
PID
File
PID
PID
PID
4
9

50. Блокировка

PID
READ
File
PID
PID
PID
WRITE
PID
5
0

51. Блокировка

PID
PID
Exclusive lock
File
PID
Exclusive lock
PID
PID
5
1

52. Блокировка

PID
PID
File
PID
PID
PID
5
2

53. Блокировка

PID
PID
File
PID
PID
PID
5
3

54. Блокировка

PID
PID
File
PID
PID
PID
5
4

55. Блокировка

PID
Exclusive lock
File
PID
Exclusive lock
Exclusive lock
PID
Exclusive lock
PID
PID
5
5

56. Блокировка

PID
Exclusive lock
File
PID
Exclusive lock
Exclusive lock
PID
Exclusive lock
PID
PID
5
6

57. Блокировка

PID
Exclusive lock
File
PID
Exclusive lock
Exclusive lock
PID
Exclusive lock
PID
PID
5
7

58. Блокировка

PID
Shared 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. Общие смещения в файлах

Процесс 1
fd
Какой-то файл…
6
9

70. Общие смещения в файлах

Процесс 1
fork()
fd
Процесс 2
fd
Какой-то файл…
7
0

71. Общие смещения в файлах

Процесс 1
fork()
fd
Процесс 2
fd
Position
Какой-то файл…
7
1

72. Общие смещения в файлах

Процесс 1
fork()
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 stdout
stdin sort stdout
stdin uniq stdout
stdin wc
8
9

90. Неименованные каналы

who stdout
stdin sort stdout
stdin uniq stdout
stdin wc
9
0

91. Неименованные каналы

who stdout
stdin sort stdout
stdin uniq stdout
stdin wc
Канал 1
9
1

92. Неименованные каналы

who stdout
stdin sort stdout
Канал 1
stdin uniq stdout
stdin wc
Канал 2
9
2

93. Неименованные каналы

who stdout
stdin 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]
English     Русский Rules