๐ง Trace00
EOF(ctrl + d) ์ ๋ ฅ์ ๋ฐ์ผ๋ฉด ํ๋ก๊ทธ๋จ์ ์ข ๋ฃ์์ผ์ผ ํฉ๋๋ค.
main๋ฌธ์ ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ด๋ฏธ ๊ตฌํ๋์ด ์๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
while(1)์ ํตํด ์์ ๊ณ์ ์คํ์ํค๋ค๊ฐ ctrl + d๊ฐ ์ ๋ ฅ๋๋ฉด ํ๋ก๊ทธ๋จ์ ์ข ๋ฃํฉ๋๋ค.
๐ง Trace01
quit ๋ช ๋ น์ด๋ฅผ built-in command๋ก ๋ฑ๋กํฉ๋๋ค.
quit์ด ์ ๋ ฅ๋๋ฉด ํ๋ก๊ทธ๋จ์ด ์ข ๋ฃ๋์ด์ผ ํฉ๋๋ค.
void eval(char *cmdline) {
cahr * argv[MAXARGS];
parseline(cmdline, argv);
builtin_cmd(argv);
return;
}
int builtin_cmd(char **argv) {
char * cmd = argv[0];
if (!strcmp(cmd, "quit")) {
exit(0);
}
return 0;
}
์ฐ์ built-in command๋ก ๋ฑ๋กํ์ฌ์ผ ํ๊ธฐ ๋๋ฌธ์ builtin_cmd ํจ์ ๋ด๋ถ์ ์์ฑํด ์ฃผ์์ต๋๋ค.
if๋ฌธ์ ํตํด ๋ค์ด์จ ์ ๋ ฅ(cmd)์ด "quit"์ ๋์ผํ ๊ฒฝ์ฐ exit(0)์ ํตํด ํ๋ก๊ทธ๋จ์ ์ข ๋ฃํ๋๋ก ๊ตฌํํ์์ต๋๋ค.
๐ง Trace02
์คํํ์ผ์ foreground job์ผ๋ก ์คํ์ํต๋๋ค.
์ด๋ ์คํ๋๋ ์คํํ์ผ์ ์ด๋ฆ์ ./myenv๋ก์จ, ํ๊ฒฝ๋ณ์๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
myenv.c ํ์ผ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
int main()
{
printf("OSTYPE=%s\n", getenv("PATH"));
fflush(stdout);
exit(0);
}
์์ฑ๋๋ ์ฝ๋๋ ์๋์ ๊ฐ์ต๋๋ค.
void eval(char *cmdline) {
char * argv[MAXARGS];
int bg = parseline(cmdline, argv);
pid_t pid;
if (builtin_cmd(argv)) {
return;
}
if ((pid = fork()) == 0) { // ์์ ํ๋ก์ธ์ค์ธ ๊ฒฝ์ฐ
execve(argv[0], argv, environ);
// ์คํํ์ผ์ ์ฐพ์ง ๋ชปํ ๊ฒฝ์ฐ ์คํ
printf("%s : Command not found\n", argv[0]); // argvp[0]์๋ ๊ด์ต์ ์ํ์ฌ ์คํํ์ผ์ ์ด๋ฆ ์ ์ฅ
exit(0); // ์ข
๋ฃ
}
if (bg) {
return;
}
// foregrond job์ ๊ฒฝ์ฐ
int child_status;
waitpid(pid, &child_status, 0);
return;
}
์ฐ์ builtin_cmd์ธ ๊ฒฝ์ฐ ์ด๋ฅผ ์คํ์ํค๊ณ ๋ฐ๋ก return ํ๋๋ก ํ์์ต๋๋ค.
์ดํ fork๋ฅผ ํตํด ์์ ํ๋ก์ธ์ค๋ฅผ ์์ฑํฉ๋๋ค.
fork()๋ 2๋ฒ returnํ๋ ํจ์์ด๋ฉฐ, ์์ ํ๋ก์ธ์ค์ธ ๊ฒฝ์ฐ ๋ฆฌํด๊ฐ์ด 0, ๋ถ๋ชจ ํ๋ก์ธ์ค์ธ ๊ฒฝ์ฐ ์์ฑ๋๋ ์์์ pid ๊ฐ์ ๋ฐํํฉ๋๋ค.
์ดํ 0๊ณผ ๋น๊ตํ๋ ์กฐ๊ฑด์ ํตํด ์์ ํ๋ก์ธ์ค์ธ์ง๋ฅผ ํ๋จํ๊ณ , ์์ ํ๋ก์ธ์ค์ธ ๊ฒฝ์ฐ execve๋ฅผ ํตํด ์คํํ์ผ์ ์ฐพ์ ์คํํ๋๋ก ํด์ฃผ์์ต๋๋ค.
execve๋ ํ์ผ ์ด๋ฆ์ ์ฐพ์ ์ ์์ด ์๋ฌ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ์๋ง -1์ ํตํด ๋ฆฌํดํ๋ฉฐ, ์ด์ธ์ ๊ฒฝ์ฐ ์ ๋ returnํ์ง ์์ผ๋ฏ๋ก ๋ฐ๋ก ์กฐ๊ฑด๋ฌธ์ ํตํด ์ฒ๋ฆฌํด์ฃผ์ง ์์์ต๋๋ค.
๋ง์ฝ return๋๋ ๊ฒฝ์ฐ '[์คํํ๊ณ ์ ํ๋ ํ์ผ ์ด๋ฆ] : Command not found' ๊ฐ ์ถ๋ ฅ๋๊ณ
exit(0)๋ฅผ ํตํด ์์ฑ๋ ์์ ํ๋ก์ธ์ค๊ฐ ์ข ๋ฃ๋ฉ๋๋ค.
๋ถ๋ชจ ํ๋ก์ธ์ค์ ๊ฒฝ์ฐ์๋ fork๊ฐ ์์นํ ๋ถ๋ถ์ ์กฐ๊ฑด๋ฌธ์ ๊ฑธ๋ฆฌ์ง ์๊ณ ๋์ด๊ฐ์ background job์ธ์ง foreground job์ธ์ง๋ฅผ ํ๋จํ๊ฒ ๋ฉ๋๋ค.
parseline์ ์ฝ๋ ๋ง์ง๋ง ๋ถ๋ถ์ ๋ณด๋ฉด ๋ค์ ์ฝ๋๊ฐ ์๋๊ฒ์ ์ ์ ์์ต๋๋ค.
์ฆ parseline์ ์ ๋ ฅ๋ ๋ช ๋ น์ด์ ๋ง์ง๋ง์ &๊ฐ ์๋ ๊ฒฝ์ฐ 1์ ๋ฐํ์ํต๋๋ค.
eval ํจ์์ ์์ ๋ถ๋ถ์์ int bg = parseline()์ ํตํด, background job์ผ๋ก ์คํ์์ผ์ผ ํ๋์ง์ ๋ํ ์ฌ๋ถ๋ฅผ ๋ฐ์์ต๋๋ค.
trace02์์๋ background job์ ๊ฒฝ์ฐ ์๋ฌด๋ฐ ์ฒ๋ฆฌ๋ฅผ ํ์ง ์์๋ ๋๋ฏ๋ก, ๋ฐ๋ก return์์ผ์ฃผ๋๋ก ์ฝ๋๋ฅผ ์์ฑํ์์ต๋๋ค.
foreground job์ ๊ฒฝ์ฐ fork()๋ก ์์ฑ๋ ์์ ํ๋ก์ธ์ค๋ฅผ waitpid๋ฅผ ํตํด ์ ๊ฑฐํด ์ค์ผ๋ก์จ ์ข๋น ํ๋ก์ธ์ค๋ฅผ ๋ฐฉ์งํ๋๋ก ์ฝ๋๋ฅผ ์์ฑํ์์ต๋๋ค.
๐ง Trace03
foreground job์ argument ์์ด ์คํ์ํต๋๋ค.
Trace02์ ๋ค์ ์ฝ๋๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
execve(argv[0], argv, environ);
argv๋ฅผ ๋๋ฒ์งธ ์ธ์๋ก ๋๊น์ผ๋ก์จ, ๋งค๊ฐ๋ณ์๋ฅผ ํจ๊ป ์ ๋ฌํ์์ต๋๋ค.
์ด๋ ๋งค๊ฐ๋ณ์๊ฐ ์๋ค๋ฉด ๋งค๊ฐ๋ณ์ ์์ด ์คํ๋๋ฏ๋ก, ๋ฐ๋ก ์ฝ๋์ ์์ ์์ด Trace03์ด ํต๊ณผํฉ๋๋ค.
๐ง Trace04
foreground job์ argument์ ํจ๊ป์คํ์ํต๋๋ค.
Trace02์์ argv๋ฅผ ๋๋ฒ์งธ ์ธ์๋ก ๋๊น์ผ๋ก์จ, ๋งค๊ฐ๋ณ์๋ฅผ ํจ๊ป ์ ๋ฌํ์์ต๋๋ค.
์ด๋ ๋งค๊ฐ๋ณ์๊ฐ ์๋ค๋ฉด ๋งค๊ฐ๋ณ์ ์์ด ์คํ๋๋ฏ๋ก, ๋ฐ๋ก ์ฝ๋์ ์์ ์์ด Trace04๊ฐ ํต๊ณผํฉ๋๋ค.
๐ง Trace05
background job์ ์คํํฉ๋๋ค.
background job์ wait, ํน์ waitpid๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.(์ ํํ๋ ์ฌ์ฉํ๋ค๋ฉด ๊ทธ๊ฒ์ background job์ด ์๋๊ฒ ๋ฉ๋๋ค.)
๋ฐ๋ผ์ ์์ ํ๋ก์ธ์ค์ ์ข ๋ฃ๋ฅผ ์ฒ๋ฆฌํด ์ค ํ์๊ฐ ์๋๋ฐ, ์ด๋ Trace05์์๋ ์๊ตฌํ์ง ์์ผ๋ฏ๋ก ์๊ตฌํ๋ Trace๋ก ๋๊ธฐ๋๋ก ํ๊ฒ ์ต๋๋ค.
์ฐ์ Trace05๋ myspin1์ ์คํํ์์ ๋ ๋ค์๊ณผ ๊ฐ์ด ์ถ๋ ฅ๋์ด์ผ ํจ์ tshref๋ฅผ ํตํด ํ์ธํ์์ต๋๋ค.
(1)์ JId(Job Id), 3425256์ pid, ./myspin1 & ์ ์ปค๋งจ๋๋ผ์ธ์ ์ ๋ ฅํ ๋ช ๋ น์ด๋ฅผ ์๋ฏธํฉ๋๋ค.
์ฆ ์ด์ ๋ง์ถ์ด ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
void eval(char *cmdline) {
char * argv[MAXARGS];
int bg = parseline(cmdline, argv);
pid_t pid;
if (builtin_cmd(argv)) {
return;
}
if ((pid = fork()) == 0) { // ์์ ํ๋ก์ธ์ค์ธ ๊ฒฝ์ฐ
execve(argv[0], argv, environ);
// ์คํํ์ผ์ ์ฐพ์ง ๋ชปํ ๊ฒฝ์ฐ ์คํ
printf("%s : Command not found\n", argv[0]); // argvp[0]์๋ ๊ด์ต์ ์ํ์ฌ ์คํํ์ผ์ ์ด๋ฆ ์ ์ฅ
exit(0); // ์ข
๋ฃ
}
// ์์ ํ๋ก์ธ์ค๊ฐ ์๋ ๊ฒฝ์ฐ jobs์ ์ถ๊ฐํฉ๋๋ค.
addjob(jobs, pid, ((bg == 1) ? BG : FG), cmdline);
if (bg) {
printf("(%d) (%d) %s", pid2jid(pid), pid, cmdline);
return;
}
// foregrond job์ ๊ฒฝ์ฐ
int child_status;
waitpid(pid, &child_status, 0);
deletejob(jobs, pid); // jobs์์ ์ ๊ฑฐ๋ ์์์ ์ญ์ ํฉ๋๋ค.
return;
}
์์ ๊ฐ์ด ์ฝ๋๋ฅผ ์์ฑํด์ฃผ๋ฉด trace05๊ฐ ํต๊ณผํ๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
๐ง Trace06
foreground job๊ณผ background job์ ์คํํฉ๋๋ค
์ด์ ๊น์ง์ Trace์์ foreground job๊ณผ backgound job์ ์คํ์ํค๋ ์ฝ๋๋ฅผ ๋ชจ๋ ์์ฑํ์์ต๋๋ค.
๋ฐ๋ผ์ Trace05์ ์ฝ๋์ ๋์ผํฉ๋๋ค.
๐ง Trace07
jobs ๋ช ๋ น์ด๋ฅผ built-in command๋ก ๋ฑ๋กํฉ๋๋ค.
jobs ์ ๋ ฅ ์ jobs์ ๋ฑ๋ก๋ job๋ค์ ์ ๋ณด๋ฅผ ๋ชจ๋ ์ถ๋ ฅํฉ๋๋ค.
์ฐ์ job๋ค์ ์ ๋ณด ์ถ๋ ฅ์ listjobs ํจ์๋ก ์ด๋ฏธ ์ ์๋์ด ์์ต๋๋ค.
์ฆ ์ด๋ฅผ ๋จ์ง built-in command๋ก ๋ฑ๋กํ์ฌ ์ฌ์ฉํด์ฃผ๋ฉด Trace07์ ํต๊ณผํ ์ ์๊ณ , ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
int builtin_cmd(char **argv) {
char *cmd = argv[0];
// ๋ช
๋ น์ด๊ฐ quit์ธ ๊ฒฝ์ฐ
if (!strcmp(cmd, "quit")) {
exit(0);
}
// trace07 : jobs ์ถ๊ฐ
if (!strcmp(cmd, "jobs")) {
listjobs(jobs, 1);
return TRUE;
}
return FALSE;
}
eval ํจ์ ๋ถ๋ถ์ ์์ ๋์ง ์์ต๋๋ค.
๐ง Trace08
SIGINT ์๊ทธ๋์ foreground job์๊ฒ๋ก ๋ณด๋ ๋๋ค.
foreground job์ SIGINT๋ฅผ ๋ฐ์ผ๋ฉด ํด๋น ์๊ทธ๋์ ๋ฐ์์ํจ process๋ฅผ ์ข ๋ฃ(terminate)์ํต๋๋ค.
์ฐ์ trace08์ ์ค๋ช ์ ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ด myintp๋ฅผ ์คํ์ํค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
์ด๋ ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ก์จ, SIGINT๋ฅผ getppid()๋ฅผ ํตํด ์์ ์ ๋ถ๋ชจ ํ๋ก์ธ์ค์๊ฒ ์ก์ ํ๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ tshref๋ฅผ ํตํด ์คํ์์ผ ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ถ๋ ฅ๋๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
[1]์ job id,
(3439063)์ pid,
by signal 2์์ 2๋ ์์ํ๋ก์ธ์ค๋ฅผ ์ข ๋ฃํ๋๋กํ ์ ํธ์ ๋ฒํธ๋ฅผ ์๋ฏธํฉ๋๋ค.
์ด๋ ์๊ทธ๋ 2๋ฒ์ SIGINT๋ฅผ ์๋ฏธํฉ๋๋ค.
๋ฐ๋ผ์ ์์์ด SIGINT ์๊ทธ๋์ ๋ฐ๊ณ ์ข ๋ฃ๋์๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
๋ํ tsh.c์ main์ ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ด sigint_handler์ sigtstp_handler, sigchld_handler๊ฐ ๋ฏธ๋ฆฌ ๋ฑ๋ก๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
์ด์ Trace08์ ๊ณผ์ ์ ์ดํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์ฐ์ tsh ์์์ myintp ์คํํ์ผ์ ์คํํฉ๋๋ค.
myintp์์๋ ๋ถ๋ชจ ํ๋ก์ธ์ค์ pid๋ฅผ ์์๋ธ ๋ค, ํด๋น pid๋ก SIGINT ์๊ทธ๋์ ์ก์ ํฉ๋๋ค.
๋ถ๋ชจ ํ๋ก์ธ์ค(tsh ์)์์๋ ์ด๋ฅผ sigint_handler๋ฅผ ํตํด ๋ฐ์๋ธ ํ, jobs์ ๋ฑ๋ก๋ job๋ค ์ค foreground์์ ์๋ํ๋ ์์ , ์ฆ myintp์ pid๋ฅผ ์์๋ ๋๋ค.
์ดํ ํด๋น pid์ ๋ค์ SIGINT๋ฅผ ๋ณด๋ด๊ฒ ๋ฉ๋๋ค.
myintp์์๋ SIGINT handler๊ฐ ์ ์๋์ด ์์ง ์์ผ๋ฏ๋ก(ํธ๋ค๋ฌ๋ ๋ถ๋ชจ๋ก๋ถํฐ ์์๋์ง ์์ต๋๋ค) ๊ธฐ๋ณธ ๋์์ผ๋ก ์๋ํ๋ฉฐ, ๋ฐ๋ผ์ ํ๋ก์ธ์ค๊ฐ ์ข ๋ฃ๋ฉ๋๋ค.
myintp ํ๋ก์ธ์ค๊ฐ ์ข ๋ฃ๋์์ผ๋ฏ๋ก SIGCHLD ์๊ทธ๋์ด ๋ถ๋ชจ ์๊ทธ๋์๊ฒ ์ ๋ฌ๋ฉ๋๋ค.
๋ถ๋ชจ ํ๋ก์ธ์ค์์๋ ์ด๋ฅผ sigchld_handler๋ฅผ ํตํด ๋ฐ์๋ธ ํ, waitpid๋ฅผ ํตํด ์ข ๋ฃ๋ ์์ ํ๋ก์ธ์ค๊ฐ ์ข๋น๊ฐ ๋์ง ์๋๋ก ์์์ ํ์ํฉ๋๋ค.
WIFSIGNALED(child_status)๋ ์์ ํ๋ก์ธ์ค๊ฐ ์ด๋ค ์๊ทธ๋์ ํตํด ์ข ๋ฃ๋ ๊ฒฝ์ฐ true๋ฅผ ๋ฆฌํดํฉ๋๋ค.
๋ฐ๋ผ์ WIFSIGNALED๋ฅผ ์ฌ์ฉํ์ฌ ์์ ํ๋ก์ธ์ค๊ฐ SIGINT๋ฅผ ํตํด ์ข ๋ฃ๋ ๊ฒฝ์ฐ WTERMSIG๋ฅผ ํตํด ์์ํ๋ก์ธ์ค๋ฅผ ์ข ๋ฃํ๋๋กํ ์๊ทธ๋์ ๋ฒํธ(SIGINT)๋ฅผ ์ป์ด๋ด ์ด๋ฅผ ํตํด ์ ๋ณด๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
์ด๋ฅผ ์ํ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
void eval(char *cmdline) {
// Blockํ ์๊ทธ๋
sigset_t mask;
// ์ด์ Block ์ํ ์ ์ฅ์ฉ ์๊ทธ๋
sigset_t prev;
sigemptyset(&mask); // ๋ชจ๋ ์๊ทธ๋ 0์ผ๋ก ์ฑ์ฐ๊ธฐ
sigaddset(&mask, SIGINT); // SIGINT 1๋ก Block
sigaddset(&mask, SIGCHLD); // SIGCHLD 1๋ก Block
char *argv[MAXARGS];
int bg = parseline(cmdline, argv);
if (builtin_cmd(argv)) {
return;
}
sigprocmask(SIG_BLOCK, &mask, &prev); // Block ์ถ๊ฐํ๊ธฐ
pid_t pid;
if ((pid = fork()) == 0) { // ์์ ํ๋ก์ธ์ค์ธ ๊ฒฝ์ฐ
// SIGNAL Block ์ด์ ์ํ๋ก ๋ณต์
// execve ์คํ ์ blocked๋ ๋ถ๋ชจ๋ก๋ถํฐ ์์๋๋ฏ๋ก ์ธ๋ธ๋ฝ ํด์ฃผ๊ณ ์คํํด์ผ ํจ.
sigprocmask(SIG_SETMASK, &prev, NULL);
execve(argv[0], argv, environ);
printf("%s : Command not found\n\n", argv[0]);
exit(0);
}
// ์์ ํ๋ก์ธ์ค๊ฐ ์๋ ๊ฒฝ์ฐ jobs์ ์ถ๊ฐํฉ๋๋ค.
addjob(jobs, pid, ((bg == 1) ? BG : FG), cmdline);
if (bg) {
printf("(%d) (%d) %s", pid2jid(pid), pid, cmdline);
// SIGNAL Block ์ด์ ์ํ๋ก ๋ณต์
sigprocmask(SIG_SETMASK, &prev, NULL);
return;
}
while (1) { // SIGCHLD signal์ ํตํด ์์ ํ๋ก์ธ์ค ์ ๊ฑฐํ ๋๊น์ง ๋ฐ๋ณต
if (pid != fgpid(jobs)) {
break;
}
sigsuspend(&prev);
}
// SIGNAL Block ์ด์ ์ํ๋ก ๋ณต์
sigprocmask(SIG_SETMASK, &prev, NULL);
return;
}
void sigchld_handler(int sig) {
int child_status = 0;
pid_t pid;
while ((pid = waitpid(-1, &child_status, WNOHANG)) > 0) {
//์์ํ๋ก์ธ์ค๊ฐ ์ด๋ค ์๊ทธ๋๋๋ฌธ์ ์ข
๋ฃ๋์๋ค๋ฉด ์ฐธ์ ๋ฐํ
if (WIFSIGNALED(child_status)) {
printf("Job [%d] (%d) terminated by signal %d\n",
pid2jid(pid),
pid,
WTERMSIG(child_status));
deletejob(jobs, pid);
} else {
deletejob(jobs, pid);
}
}
return;
}
void sigint_handler(int sig) {
pid_t pid = fgpid(jobs);
if (pid != 0) {
kill(pid, sig);
}
return;
}
๐ง Trace09
SIGTSTP ์๊ทธ๋์ foreground job์๊ฒ๋ก ๋ณด๋ ๋๋ค.
foreground job์ SIGTSTP๋ฅผ ๋ฐ์ผ๋ฉด ํด๋น ์๊ทธ๋์ ๋ฐ์์ํจ process๋ฅผ ์ ์ง ์ํ๋ก ๋ง๋ญ๋๋ค.
Trace09๋ Trace08๊ณผ ๋น์ทํ์ง๋ง ์ค์ํ ์ฐจ์ด์ ์ด ์กด์ฌํฉ๋๋ค.
์ฒซ๋ฒ์งธ ์ฐจ์ด์ ์ SIGTSTP๋ฅผ ๋ฐ์ผ๋ฉด foreground job์ด ์ข ๋ฃ๋๋ ๊ฒ์ด ์๋ ์ ์ง๋์ด์ผ ํฉ๋๋ค.
๋ฐ๋ผ์ deletejob์ ์ํํด์ฃผ์ง ์์ผ๋ฉฐ, state๋ฅผ ST๋ก ๋ณ๊ฒฝํด ์ฃผ์ด์ผ ํฉ๋๋ค.
ST๋ ๋ค์๊ณผ ๊ฐ์ด ๋ฏธ๋ฆฌ ์ ์๋์ด ์์ต๋๋ค.
์ฐ์ SIGTSTP๋ฅผ Blockํ๊ธฐ ์ํด eval ํจ์๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์์ ํด ์ฃผ์์ต๋๋ค.
void eval(char *cmdline) {
// Blockํ ์๊ทธ๋
sigset_t mask;
// ์ด์ Block ์ํ ์ ์ฅ์ฉ ์๊ทธ๋
sigset_t prev;
sigemptyset(&mask); // ๋ชจ๋ ์๊ทธ๋ 0์ผ๋ก ์ฑ์ฐ๊ธฐ
sigaddset(&mask, SIGINT); // SIGINT 1๋ก Block
sigaddset(&mask, SIGCHLD); // SIGCHLD 1๋ก Block
sigaddset(&mask, SIGTSTP); // SIGTSTP 1๋ก Block
char *argv[MAXARGS];
int bg = parseline(cmdline, argv);
if (builtin_cmd(argv)) {
return;
}
sigprocmask(SIG_BLOCK, &mask, &prev); // Block ์ถ๊ฐํ๊ธฐ
pid_t pid;
if ((pid = fork()) == 0) { // ์์ ํ๋ก์ธ์ค์ธ ๊ฒฝ์ฐ
// SIGNAL Block ์ด์ ์ํ๋ก ๋ณต์
sigprocmask(SIG_SETMASK, &prev, NULL);
execve(argv[0], argv, environ);
printf("%s : Command not found\n\n", argv[0]);
exit(0);
}
// ์์ ํ๋ก์ธ์ค๊ฐ ์๋ ๊ฒฝ์ฐ jobs์ ์ถ๊ฐํฉ๋๋ค.
addjob(jobs, pid, ((bg == 1) ? BG : FG), cmdline);
if (bg) {
printf("(%d) (%d) %s", pid2jid(pid), pid, cmdline);
// SIGNAL Block ์ด์ ์ํ๋ก ๋ณต์
sigprocmask(SIG_SETMASK, &prev, NULL);
return;
}
while (1) { // SIGCHLD signal์ ํตํด ์์ ํ๋ก์ธ์ค ์ ๊ฑฐํ ๋๊น์ง ๋ฐ๋ณต
if (pid != fgpid(jobs)) {
break;
}
sigsuspend(&prev);
}
// SIGNAL Block ์ด์ ์ํ๋ก ๋ณต์
sigprocmask(SIG_SETMASK, &prev, NULL);
return;
}
์ดํ sigchld_handler๋ ๋ค์๊ณผ ๊ฐ์ด ์์ ํ์์ต๋๋ค.
void sigchld_handler(int sig) {
int child_status = 0;
pid_t pid;
while ((pid = waitpid(-1, &child_status, WNOHANG | UNTRACED)) > 0) {
if (WIFSIGNALED(child_status)) {
printf("Job [%d] (%d) terminated by signal %d\n",
pid2jid(pid),
pid,
WTERMSIG(child_status));
deletejob(jobs, pid);
}
if (WIFSTOPPED(child_status)) {
getjobpid(jobs, pid)->state = ST;
printf("Job [%d] (%d) stopped by signal %d\n",
pid2jid(pid),
pid,
WSTOPSIG(child_status)); // ์ ์ง๋ ์ํ๊ฐ ๋๋๋ก ํ ์๊ทธ๋ ๋ฒํธ
}
if (WIFEXITED(child_status)) {
deletejob(jobs, pid);
}
}
}
SIGCHLD ๋ ์์์ด ์ ์งํ ๊ฒฝ์ฐ์๋ ๋ฐ์ํ๋ฏ๋ก, ๊ฒฐ๊ตญ mytstpp ๊ฐ SIGTSTP ๋ก ์ธํด ์ ์ง๋ ๊ฒฝ์ฐ ๋ถ๋ชจ ํ๋ก์ธ์ค์๊ฒ SIGCHLD ๊ฐ ์ ๋ฌ๋ฉ๋๋ค.
Trace08๊ณผ๋ ๋ฌ๋ฆฌ ์ ์ง๋ ํ๋ก์ธ์ค๋ฅผ ์ก์์์ Stop ์ํ๋ก ๋ฐ๊ฟ์ฃผ์ด์ผ ํ๋ฏ๋ก WNOHANG | WUNTRACED๋ฅผ ํตํด ์ข ๋ฃ๋๊ฑฐ๋ ์ ์งํ ์์์ pid๋ฅผ ๋ฐ์์ค๊ฑฐ๋ ์๋ค๋ฉด ๋ฐ๋ก return๋๋๋ก ํด์ฃผ์์ต๋๋ค.
์ดํ WIFSTOPPED๋ฅผ ํตํด ์์์ด ์ ์งํ ๊ฒฝ์ฐ ์๊ตฌ์ฌํญ์ ๋ง๊ฒ ์ฒ๋ฆฌํด ์ฃผ๋๋ก ์ฝ๋๋ฅผ ์์ฑํ์์ต๋๋ค.
sigtstp_handler๋ sigint_handler์ ๋์ผํฉ๋๋ค.
void sigtstp_handler(int sig) {
pid_t pid = fgpid(jobs);
if (pid != 0) {
kill(pid, sig);
}
return;
}
๐ง Trace10
SIGTERM์๊ทธ๋์ background job์๊ฒ๋ก ๋ณด๋ ๋๋ค.
foreground job์ SIGTERM๋ฅผ ๋ฐ์ผ๋ฉด ํด๋น ์๊ทธ๋์ ๋ฐ์์ํจ process๋ฅผ ์ข ๋ฃ์ํต๋๋ค.
์๋ trace10.txt ํ์ผ์ ํตํด myspin1 ํ๋ก๊ทธ๋จ์ background๋ก 5์ด๋์ ์คํ์ํค๋ฉฐ,
์ดํ /bin/kill์ ํตํด SIGTERM์ ๋ฐ์์ํค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค. (์๋ฌด๋ฐ ์ธ์๊ฐ ์์ผ๋ฏ๋ก ๊ธฐ๋ณธ ๋์์ด SIGTERM ์ ๋๋ค.)
Trace09์ฝ๋์์ sigchild_handler ์ฝ๋๋ฅผ ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
void sigchld_handler(int sig) {
int child_status = 0;
pid_t pid;
while ((pid = waitpid(-1, &child_status, WNOHANG | WUNTRACED)) > 0) {
if (WIFSIGNALED(child_status)) {
printf("Job [%d] (%d) terminated by signal %d\n",
pid2jid(pid),
pid,
WTERMSIG(child_status));
deletejob(jobs, pid);
}
if (WIFSTOPPED(child_status)) {
getjobpid(jobs, pid)->state = ST;
printf("Job [%d] (%d) stopped by signal %d\n",
pid2jid(pid),
pid,
WSTOPSIG(child_status)); // ์ ์ง๋ ์ํ๊ฐ ๋๋๋ก ํ ์๊ทธ๋ ๋ฒํธ
}
if (WIFEXITED(child_status)) {
deletejob(jobs, pid);
}
}
}
Trace10์ ๊ฒฝ์ฐ SIGTERM์ ์ํด ์ข ๋ฃ๋๋ฏ๋ก WIFSIGNALED์ ๊ฑธ๋ ค์ ์ฒ๋ฆฌ๋ฉ๋๋ค.
๐ง Trace11 & Trace12
์์ ํ๋ก์ธ์ค๊ฐ ์๊ธฐ ์์ ์๊ฒ SIGINT, SIGTSTP ์๊ทธ๋์ ์ ์กํฉ๋๋ค.
Trace08, Trace09๋ฅผ ์ ํํ ๊ตฌํํ์๋ค๋ฉด ์ฌ๋ฐ๋ฅด๊ฒ ๋์ํฉ๋๋ค.
Trace11๊ณผ Trace12์์๋ ๊ฐ๊ฐ myints์ mytstps๋ฅผ ์ฌ์ฉํ๋๋ฐ ๊ฐ๊ฐ์ ํ์ผ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๋ ํ์ผ ๋ชจ๋ getpid() ๋ฅผ ํตํด ์๊ธฐ ์์ ์ pid๋ฅผ ์ป์ด์จ ํ, ์๊ทธ๋์ ๋ฐ์์ํต๋๋ค.
์ ๋ ๊ฒฝ์ฐ ๋ชจ๋ ์๊ธฐ ์์ ์๊ฒ ์๊ทธ๋์ด ๋์ฐฉํ๋ฏ๋ก Trace08, Trace09์ ๋์ผํ ๊ณผ์ ์ ๊ฑฐ์ณ ์๊ทธ๋์ด ์ฒ๋ฆฌ๋๋ฏ๋ก ๋ฐ๋ก ๊ตฌํํด ์ค ํ์ ์์ด ํต๊ณผํ ์ ์์ต๋๋ค.