System Programming Ch9 - Ch10
๐กย Chap_9
Sessions
์์คํ ํ๋ก๊ทธ๋๋ฐ์์์ session์?
โ ํ๋ ๋๋ ๊ทธ ์ด์์ ํ๋ก์ธ์ค ๊ทธ๋ฃน
Controlling Terminal
- session leader : ๋ค๋ฅธ๋ง๋ก login shell ๋๋ controlling process
- ์ด๋ค ์๋ฒ์ ์ ์ํ์ฌ ์ฐ๊ฒฐ์ฑ์ ๊ฐ์ง๊ฒ ๋จ โ session
terminal์ ํตํด์ ๋ช ๋ น์ด๋ฅผ ์น๊ณ , ์ฝ๋ฉ์ ํ ์ ์๊ฒ ๋จ (login shell์ ํตํด์)
โ login shell์ด session์ ์ ์งํ๋ ๊ฒ์ด๋ฉด์๋, session leader๊ฐ ๋๋ ๊ฒ
- ์ ์ํ ํฐ๋ฏธ๋์ ํตํด process 1๋ถํฐ 5๊น์ง๋ฅผ ๋ค ๋ค๋ฃฐ ์ ์๊ฒ๋จ(ํ๋ก์ธ์ค๋ฅผ ๋ง๋ค์ด๋ผ์๋, ์ง์ธ์๋, ๋ฉ์ถ์๋,.. ๊ถํ์ด ์๋ค๋ฉด)
- controlling terminal : pts ๋๋ tty๋ผ๊ณ ํจ, ์ฆ ์ ์ํ์ ๋ ๋ถ์ฌ๋ฐ๋ ์ด shell์ ์ ์ดํ๋ ์๋ฒ์์ ๋ถ์ฌํ ์ด๋ค๊ฐ
- controlling terminal์์ hang-up signal์ ์ฃผ๋ฉด session leader๋ก ๊ฐ๊ณ ,
- terminal input and terminal-generated signals๋ฅผ ์ฃผ๋ฉด foreground process group์ผ๋ก ๊ฐ
- hang-up signal : ์ฌ์ฉ์๊ฐ ์ ๊น ๋ฉ์ถ๋ผ๊ณ ์ฃผ๋ ๋ช ๋ น์ด, session leader๊ฐ ๋ฐ์ํ๊ฒ ๋จ
terminal input and terminal-generated signals : ์ธํฐ๋ฝํธ
- foreground ์ background์ ์ฐจ์ด
- background : &์ ๋ถ์ด๋ฉด ๋ฐฑ๊ทธ๋ผ์ด๋๋ก ๋์, ํฐ๋ฏธ๋์ ํํํด์ฃผ์ง ์๊ณ ์์์ ๋๋ฆผ, shell์ ๊ถํ์ ๋ด์ด์ฃผ์ง ์์ผ๋ฉด์ ๋์, ํ๋ก์ธ์ค๋ฅผ ๋๋ ค๋๊ณ ๋ค๋ฅธ์ผ์ ํ ์ ์์
- foreground : &์ ๋ถ์ด์ง ์์ผ๋ฉด ํฌ๊ทธ๋ผ์ด๋๋ก ๋์, ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ค, shell์ ๊ถํ์ ๋บ๊น, ํฌ๊ทธ๋ผ์ด๋๋ก ๋๋ ํ๋ก์ธ์ค๋ ๋๋ ๋๊น์ง ๋ค๋ฅธ ์ผ์ ํ ์ ์์
๐กย Chap_10
Interrupted System Calls
Automatic restarting
- nioctl, read, readv, write, writev, wait, and waitpid โฆ ์ด๋ฐ ํจ์๋ค์ ์์ฃผ ๋๋ฆฐ ์ฌ๋ก์ฐ์์คํ ์ฝ ํจ์๋ค์ด๋ค. (slowsc)
- ๊ทธ๋ฐ๋ฐ ์๋ค๊ฐ ๋ชจ์ข ์ ์ด์ ๋ก ๋ฉ์ถ์์ ๋ ์์ํ ๋ธ๋ก๋ ์ ์์, ๊ทธ๋ฌ๋ฉด ํ๋ก๊ทธ๋จ์ ๊ทธ๋ฅ ๊บผ์ผ๋จ, ๊ทผ๋ฐ ๊ทธ๋ฅ ๋์๋ ์๊ณ ๋ณต๊ตฌ๋ฅผ ํด์ผ๋จ
- ์ด ๋ณต๊ตฌ๋ฅผ ์๋์ ์ผ๋ก ํด์ฃผ๋๊ฒ automatic restarting
- ์ฌ๋ก์ฐ์์คํ ์ฝ ํจ์์์ ์ธํฐ๋ฝํธ ๋ฐ์ํ์๋, ๋ฌดํ๋ธ๋ก์ ํด์ํ๊ธฐ ์ํด ์๋์ผ๋ก ์ฌ์คํ ํด์ฃผ๋ ๊ฒ.
kill and raise Fuction
- kill : ํ๋ก์ธ์ค๋ฅผ ์ฃฝ์ด๋(์์ ๋, ์ ๊ฑฐํ๋, ์ง์ฐ๋) ํจ์
- raise : ๋ ์์ ํ๋ก์ธ์ค์๊ฒ ์๊ทธ๋์ ๋๊ฒจ์ฃผ๋ ํจ์
#include <signal.h>
int kill(pid_t pid, int signo)
int raise(int signo);
- kill ํ๋ฉด ์ด๋ค ํ๋ก์ธ์ค๋ฅผ ์ฃฝ์ผ์ง pid(process number)๋ฅผ ๋๊ฒจ์ฃผ๊ฒ ๋์ด์์, ๊ทผ๋ฐ raise๋ ํ๋ก์ธ์ค ์์ด๋๋ฅผ ๋๊ฒจ์ฃผ์ง ์์, ๊ทธ ์ด์ ๋ ๋ ์์ ์๊ฒ ๋ณด๋ด๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์
alarm and pause Function (์ํ๋ฌธ์ ๋์ฌ๊ฑฐ์)
(์๋ ์ฝ๋๋ ๋ชจ๋ ๋ผ์ธ ๋ค ์ดํดํด์ผ๋จ)
#includeย <signal.h>
#includeย <unistd.h>
static void
sig_alrm(int signo)
{
ย /* nothing to do, just return to wake up the pause */
}
unsigned int
sleep1(unsigned int nsecs)
{
ย if (signal(SIGALRM, sig_alrm) == SIG_ERR) //SIGALARM์ด ๋ฐ์ํ๋ฉด ๋๋ฒ์งธ ์ธ์, sig_alrm์ ์คํ์์ผ์ฃผ๋ผ๋ ์๋ฏธ
ย return(nsecs);
ย alarm(nsecs);ย /* start the timer */
ย pause();ย /* next caught signal wakes us up */
ย return(alarm(0));ย /* turn off timer, return unslept time */
}
<์ด ์ฝ๋๊ฐ ์ ์์ ์ผ๋ก ๋์ํ ๊ฒฝ์ฐ>
signal(SIGALRM, sig_alrm)
์ SIGALARM(์ค์ ๋ก ์์คํ ์ด ๋ด๋ฑ์ ์๊ทธ๋)์ด ๋ฐ์ํ๋ฉด ๋๋ฒ์งธ ์ธ์, sig_alrm์ ์คํ์์ผ์ฃผ๋ผ๋ ์๋ฏธ- ๊ทผ๋ฐ ์คํ์ด ์๋๊ณ ์๋ฌ๊ฐ ๋๋ฉด ๋ฆฌํดํจ
alarm : SIGALRM์ ๋ง๋ค์ด์ค, ์ธ์์ธ nsecs๋ ์ง์ง ์ด, ์ธ์๋ก ๋์ด์จ ์๊ฐ 2๋ฉด 2์ด๋ค์ ์๋ ํจ์ ์ํ, ์๊ทธ๋ ๋ฐ์, 2์ด๊ฐ ๋๊ธฐ ์ ์๋ ๊ณ์ ๋ค์๋ผ์ธ ์คํํด๊ฐ
alarm์ ์ธ์๋ก ๋ค์ด์จ ์ด ์๊ฐ ์ดํ์ SIGALARM์ ๋ฐ์์ํค๋ ํจ์
- pause : ์๊ทธ๋์ด ๋ญ๋ ๊ฐ์ ์๊ทธ๋์ด ๋ฐ์ํ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๋ผ๋ ํจ์, 2์ด๊ฐ ๋ ๋๊น์ง pause์์ ๊ธฐ๋ค๋ฆฌ๋ค๊ฐ signalํจ์ ๋์ํด์ sig_alrm ํธ์ถํด์ ์ํ, ๊ทธ๋ฌ๊ณ ๋ค์ ๋์์ด
- ๊ทธ ๋ค๋ก๋ alarm๊ณผ pause๋ ํ๋ฒ ์ํ๋์์ผ๋ฏ๋ก ๊ทธ๋ฅ ์ง๋๊ฐ (alarm 0๋จ, ๋์ด์ ๋์ํ์ง ์์)
<race condition>
alarm(nsecs);
์์ race condition ๋ฐ์
- scheduling์ด ๊ผฌ์ฌ์ pause๋ฅผ ๋ง๋๊ธฐ ์ ์ ์๋์ด ๋๋ ๊ฒฝ์ฐ,
- ๋ฌดํ ๋ธ๋ก์ ๊ฑธ๋ ค์ pause์ ์กํ์๊ฒ๋จ
- ๊ทธ๋์ ์ด๊ฑด ๋ง์ ์์ ์ฒ๋ฆฌํ๋ ํ๋ก๊ทธ๋จ์์๋ ์ด๋ ๋ฏ ๋ธ๋ก์ด ๋ฐ์ํด์ ์ธ ์ ์์
์์ ๊ฐ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ์ฝ๋
#includeย <setjmp.h>
#includeย <signal.h>
#includeย <unistd.h>
static jmp_bufย env_alrm;
static void
sig_alrm(int signo)
{
ย longjmp(env_alrm, 1);
}
unsigned int
sleep2(unsigned int nsecs)
{
ย if (signal(SIGALRM, sig_alrm) == SIG_ERR)
ย return(nsecs);
ย if (setjmp(env_alrm) == 0) { //์๋์ setjmp์์๋ค๊ฐ ๋ฃ์ด์ค
ย alarm(nsecs);ย /* start the timer */
ย pause();ย /* next caught signal wakes us up */
ย }
ย return(alarm(0));ย /* turn off timer, return unslept time */
}
- setjmp๋ฅผ ๊ฑธ๊ณ ์๋์ด ๋๊ฒ๋จ
- ๊ทธ๋ฌ๋ฉด sig_alrm์ด ์คํ๋์์ ๋ longjmp๋ง๋๊ณ , 1์ ๋ฐํํ๊ฒ ๋๋๊น if๋ฌธ์ ์๊ฑธ๋ฆผ, ์ฆ ๋ฌธ์ ํด๊ฒฐ
- ์๋์ ํตํด์ ๋ฐ์ํ๋ racecondition์ ์ด๋ ๊ฒ setjmp์ longjmp๋ก ํด์ ๊ฐ๋ฅ
(์๋ ์ฝ๋๋ ์์ alarm๊ณผ pause์์ ๋ฐ์ํ๋ race condition๊ณผ ๋์ผํจ)
static voidย sig_alrm(int);
int main(void)
{
ย intย n;
ย charย line[MAXLINE];
ย if (signal(SIGALRM, sig_alrm) == SIG_ERR)
ย err_sys("signal(SIGALRM) error");
ย alarm(10);
ย if ((n = read(STDIN_FILENO, line, MAXLINE)) < 0)
ย err_sys("read error");
ย alarm(0);
ย write(STDOUT_FILENO, line, n);
ย exit(0);
}
static void sig_alrm(int signo)
{
ย /* nothing to do, just return to interrupt the read */
}
<race condition ๋ฐ์>
alarm(10);
๊ฑธ๋ฆฌ๊ณ 10์ด๋์ ๋ค์ ์ฝ๋๊ฐ ์คํ๋๊ธธ ๊ธฐ๋ํจ, ๊ทธ๋ฐ๋ฐ ์๋ฒ์์ ์ฒ๋ฆฌํด์ผ๋ ์ผ์ด ๋๋ฌด ๋ง์ ๊ฒฝ์ฐ(์ปดํจํฐ๊ฐ ๊ฐ๊ตฌ๋ฆฌ๋ค๋ ๊ฐ์ ), read๋ฅผ ์ํ ๋ชปํ๊ณ ์๋์ด ๋๋๋ฒ๋ฆฌ๋ ๊ฒฝ์ฐ- read๋ฅผ ๋ง๋๊ธฐ๋ ์ ์ ์ธํฐ๋ฝํธ๊ฐ ๊ฑธ๋ ธ๋ค ์๋๋ ์ํ์ด ์๋๊ณ ๋ฌดํ๋๊ธฐ๋ฅผ ํด๋ฒ๋ฆผ, ๋ฌดํ๋ธ๋ก(read์ ํน์ฑ)
- read๋ ์ฌ์ฉ์์ ํค๋ณด๋ ์ ๋ ฅ์ ๋ฐ์ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๋ ๊ฒ, ๊ทธ๋ฐ๋ฐ ์๋์ ๊ฐ๋ค๊ฐ ์ธํฐ๋ฝํธ๊ฐ ๊ฑธ๋ฆฌ๋ฉด readํจ์๋ ๋์ด์ ๋์ X, ๊ณ์ ๊ธฐ๋ค๋ฆผ(๋ธ๋ก ์ํ)
- read๊ฐ ๋ธ๋ก์ธ ์ํ๋ฅผ ๊บผ๋ด์ฃผ๊ฑฐ๋ read๋ฅผ ํ๋ฒ ๋ ์ํํด์ค์ผํจ
์์ ์ํฉ์ longjmp, setjmp๋ก ํด๊ฒฐํ ์ฝ๋
static voidย sig_alrm(int);
static jmp_bufย env_alrm;
int main(void)
{
ย intย n;
ย charย line[MAXLINE];
ย if (signal(SIGALRM, sig_alrm) == SIG_ERR)
ย err_sys("signal(SIGALRM) error");
ย if (setjmp(env_alrm) != 0)
ย err_quit("read timeout");
ย alarm(10);
ย if ((n = read(STDIN_FILENO, line, MAXLINE)) < 0)
ย err_sys("read error");
ย alarm(0);
ย write(STDOUT_FILENO, line, n);
ย exit(0);
}
static void sig_alrm(int signo)
{
ย longjmp(env_alrm, 1);
}
- alarm ์ธํ ์ ๋๊ฐ์๋ฐ setjmp๋ฅผ ๊ฑธ์ด์ค
- alarm ๋๋๋ฉด sig_alrm ์คํ, setjmp๋ก ์ ํํ๋๋ฐ ๋ฐํ๊ฐ 1,
- ๊ทธ๋ฌ๋ฉด if๋ฌธ์ ๊ฑธ๋ ค์
err_quit("read timeout");
๋ฐ์
sigpending Function (์ฝ๋ ์๊ธฐ)
static void sig_quit(int signo) //์ดํจ์๋ฅผ ์ดํดํ ํ์๋ X
{
ย ย printf("caught SIGQUIT\n");
ย ย if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
ย err_sys("can't reset SIGQUIT");
}
int main(void)
{
ย sigset_tย newmask, oldmask, pendmask;
ย if (signal(SIGQUIT, sig_quit) == SIG_ERR) //SIGQUIT๊ฐ ๋ฐ์ํ๋ฉด sig_quit์คํ
ย err_sys("can't catch SIGQUIT");
ย /*
ย ย * Block SIGQUIT and save current signal mask.
ย ย */
ย sigemptyset(&newmask);
ย sigaddset(&newmask, SIGQUIT);
ย if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
ย err_sys("SIG_BLOCK error");
ย sleep(5);ย /* SIGQUIT here will remain pending */
ย if (sigpending(&pendmask) < 0)
ย err_sys("sigpending error");
ย if (sigismember(&pendmask, SIGQUIT))
ย printf("\nSIGQUIT pending\n");
ย /*
ย ย * Reset signal mask which unblocks SIGQUIT.
ย ย */
ย if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
ย err_sys("SIG_SETMASK error");
ย printf("SIGQUIT unblocked\n");
ย sleep(5);ย /* SIGQUIT here will terminate with core file */
ย exit(0);
}
sigset_tย newmask, oldmask, pendmask;
: sigset_t๋ ์๋ฃํ์ธ๋ฐ ์๊ทธ๋์ ์ ์ฅํ๊ธฐ ์ํ ๋ฐ๊ตฌ๋์ (set๋๊น),์๊ทธ๋์ ์ข ๋ฅ๋ ๊ต์ฅํ ๋ง์ ๊ทธ๊ฒ๋ค์ ๋ด์ ์ ์๋๋ก ๋ง๋ค์ด์ง ์๋ฃํ์
- SIGQUIT : control + \ (๋ฉ์ถ๋ ๊ฒ)
sigemptyset(&newmask);
:char arr[100] = {0,}
์ด๋ฐ ์ญํ- newmask๋ฅผ ์น ์ด๊ธฐํ ํด์ค, ์๋ฌด๊ฒ๋ ๋ด์ง ์์ ๋ฐ๊ตฌ๋๋ก ๋ง๋ค์ด์ค
- ์ธ์๋ก ๋ค์ด์จ ์ ๋ฅผ ์๋ฌด๊ฒ๋ ๋ด์ง ์์ ๊ฑธ๋ก ๋ง๋ค์ด์ค
sigaddset(&newmask, SIGQUIT);
:- signal์ set์ ๋ํด์ฃผ๋ ํจ์
- newmask๋ผ๋ sigset์ SIGQUIT๋ผ๋ ์๊ทธ๋์ ๋ํด์ค
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
:- newmask์ ์๋ ์๊ทธ๋์ ๋ฐ์ํด๋ ๋ธ๋ก์์ผ, ์ฆ ๋ฌด์ํ๋ผ๋ ๋ป
- oldmask๋ ์ด์ ์๋ ๋ธ๋กํ ์๊ทธ๋๋ค์ด ์์์ ์๋ ์์, ์ด์ ์ ์๋ ๋ธ๋ก ๋ฆฌ์คํธ๋ค์ oldmask์๋ค๊ฐ ์ ์ฅํด๋๋ ๊ฒ, ๋ณต์์ด ํ์ํ ์ ์๊ธฐ ๋๋ฌธ์
if (sigpending(&pendmask) < 0)
: ์ง๊ธ ๋ธ๋ก ๋ฆฌ์คํธ์ ๋ญ๊ฐ ์๋์ง,- ์ธ์๋ก ๋ค์ด์๋ pendmask์๋ค๊ฐ ์ง๊ธ ๋ธ๋ก๋ ์๊ทธ๋์ ๋ฃ์ด์ค
if (sigismember(&pendmask, SIGQUIT))
: ์ฒซ๋ฒ์งธ ์ธ์๋ก ๋ค์ด๊ฐ pendmask์ SIGQUIT๊ฐ ์๋๋๋ฅผ ๋ฌผ์ด๋ณด๋ ๊ฒ
โ sigpending๊ณผ sigismember๋ ๊ทธ๋ฅ ํ์ธํ๋ ํจ์๋ค, ๊ตณ์ด ์์ด๋ ๋จ
(์ฌ๊ธฐ๊น์ง SIGQUIT ๋ธ๋กํ๋ ์ฝ๋)
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
: ์๋ block list๋ก ์๋ณต
sigaction Function
#include <signal.h>
int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);
struct sigaction {
ย void ย (*sa_handler)(int); /* addr of signal handler, */
ย ย ย ย ย ย ย ย ย ย ย /* or SIG_IGN, or SIG_DFL */
ย sigset_t sa_mask;ย ย ย ย ย ย ย /* additional signals to block */
ย int ย sa_flags;ย ย ย ย ย ย ย /* signal options */
ย ย ย ย /* alternate handler */
ย voidย (*sa_sigaction)(int, siginfo_t *, void *);
}
/* Reliable version of signal(), using POSIX sigaction().ย */
Sigfunc *
signal(int signo, Sigfunc *func)
{
ย struct sigactionย act, oact;
ย act.sa_handler = func;
ย sigemptyset(&act.sa_mask);
ย act.sa_flags = 0;
ย if (signo == SIGALRM) {
#ifdefย SA_INTERRUPT
ย act.sa_flags |= SA_INTERRUPT;
#endif
ย } else {
#ifdefย SA_RESTART
ย act.sa_flags |= SA_RESTART;
#endif
ย }
ย if (sigaction(signo, &act, &oact) < 0)
ย return(SIG_ERR);
ย return(oact.sa_handler);
}
- ์๊ทธ์ก์ ์ด๋ผ๋ ๊ตฌ์กฐ์ฒด๋ฅผ ํตํด์ ์๊ทธ์๋์ด ๋ฐ์ํ ๊ฒฝ์ฐ, ์ธํฐ๋ฝํธ๋ฅผ ๊ฑธ๋ ค๋ฉด ์ด๋ป๊ฒ ์ฝ๋๋ฅผ ์ง์ผํ๋๊ฐ.
if (signo == SIGALRM)
: sig number๊ฐ SIGALRM์ด๋ฉดSA_INTERRUPT
, sigaction interrupt ๊ฑธ์ด์ค๋ผ