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