Shell Lab
- linux에서 우리가 지금까지 사용해 왔던 Cmd와 같은 shell을 직접 구현해 보는 과제이다.
- 관련 주제
- process(fork, exec): 기본적으로 shell은 사용자의 입력을 받아 프로그램을 실행시켜주는 프로그램이라고 생각하면 편하다. 따라서 사용자의 입력에 맞는 프로그램을 실행시킬 child process를 만들고, 해당 process를 적절하게 관리하는 것이 shell lab의 주된 목표이다.
- signal(signal handling): shell에서 실행되는 child들이 parent에게 다양한 신호를 보내기도 하고, 또한 반대로
Ctrl + C
나 Ctrl + Z
와 같이 parent에서 child로 가는 신호도 있다. 이러한 신호들에 대해서 올바르게 처리하는 것
- IPC(pipe, redirection)
- 관련 함수
fork()
: child process를 만들어야지
exec()
: exec계열 함수는 정말 엄청나게 많다... 그중에서 올바른 것을 찾는 것 또한 능력이 아닐까
kill()
: parent에서 child로 signal을 보내기
signal()
: child가 보낸 signal을 올바르게 handling하기
dup2()
: I/O redirection(>
, <
) - 사실은 >>
이나 <<
같은 redirection도 있는 것 같지만... 본 과제의 spec에 포함되지는 않는다.
pipe()
: pipe 기능 구현(|
)
1. Trace 2.
- 입력받은 프로그램을 ForeGround에서 실행하기!
- 구현해야 하는 코드:
eval()
void eval(char *cmdline)
{
#define P_READ 0
#define P_WRITE 1
char *str = strdup(cmdline);
VERBOSE("eval(%s)", stripnewline(str));
free(str);
char ***argv = NULL;
char *infile = NULL;
char *outfile = NULL;
JobState mode;
sigset_t mask;
int ncmd = parse_cmdline(cmdline, &mode, &argv, &infile, &outfile);
VERBOSE("parse_cmdline(...) = %d", ncmd);
if (ncmd == -1) return;
if (ncmd == 0) return;
assert(ncmd > 0);
if (verbose) dump_cmdstruct(argv, infile, outfile, mode);
if ((ncmd == 1) && (outfile == NULL)) {
if (builtin_cmd(argv[0])) {
free_cmdstruct(argv);
return;
}
}
pid_t *pid = malloc(sizeof(pid_t) * ncmd);
if((pid[0] = fork()) < 0) {
printf("fork error: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
else if (pid[0] == 0) {
setpgid(0, 0);
if(execvp(argv[0][0], argv[0]) < 0) {
printf("%s: Command not found\n", argv[0][0]);
exit(EXIT_FAILURE);
}
}
int jid = addjob(pid[0], pid, ncmd, mode, cmdline);
if (mode == jsForeground) {
waitfg(jid);
}
else {
printjob(jid);
}
}
2. Trace 3.