[Shell Lab] Trace05, Trace 06
Trace05 는 실행파일을 Background job 으로 실행시키는 문제입니다.
trace05는 특정 형태로 출력할 것을 요구합니다. 이 형식을 확인하기 위해서 trace05.txt 파일을 열어봅시다.
#
# trace05.txt - Run a background job.
#
/bin/echo -e tsh\076 ./myspin1 \046
NEXT
./myspin1 &
NEXT
WAIT
SIGNAL
/bin/echo -e tsh\076 quit
NEXT
quit
Trace05는 myspin1 실행파일을 & 를 이용해 백그라운드 job으로 실행시키는 것을 알 수 있습니다.
tshref가 ./myspin1 &을 입력하면 어떤 것을 출력하는지 확인해봅시다.
[숫자] (숫자) command 형태로 출력하는 것을 알 수 있습니다. 논리적인 근거가 되지는 못하지만... 숫자의 모양새를 보아하니 jid, pid 를 출력하는 것 같습니다. 그러므로 출력인자에 pid2jid(pid)와, pid를 입력해줍니다. 참고로 pid2jid는 tsh.c에 이미 정의되어있는 pid를 인자로 받아 jid를 출력해주는 함수입니다.
명령어 뒤에 & 을 붙여 실행시키면 Background job으로 실행시킬 수 있었던 점을 떠올리며 Trace05번을 해결해봅시다.
Background 형태로 프로세스를 생성하기 위해서는 쉘에서 작업들을 관리하는 부분이 구현되어있어야합니다. tsh.c 파일의 struct job_t 구조체를 살펴봅시다.
job_t 구조체 내에 process id 를 저장할 변수 pid, 작업 아이디를 저장할 변수 jid(job id), 어떤 형태로 작업이 수행되는지 상태를 저장할 변수 state, 입력된 명령어를 저장할 변수 cmdline이 선언되어 있는 것을 확인할 수 있습니다.
그리고 jobs라는 job_t type의 배열을 선언함을 통해 job들을 등록 / 제거할 것임을 예상할 수 있습니다!
job을 관리하기 위한 함수들로는 다음과 같은 것들이 있습니다.
쉘의 기본구조는 cmdline을 받아 eval 하는 것이므로 eval 함수로 가서 background로 실행할 수 있도록 처리해봅시다.
최종코드
void eval(char *cmdline) {
char *argv[MAXARGS]; //command 저장
pid_t pid; // pid 이용해야함.
int bg;
//명령어를 parseline을 통해 분리
bg = parseline(cmdline, argv);
// parseline을 뜯어보면 bg 여부를 리턴하는 것을 확인할 수 있음.
//parsing된 명령어를 전달
if(!builtin_cmd(argv)) {
if ( (pid=fork()) == 0/*Child Process 체크*/) {
//Child Process인 경우, execve()수행
if ( execve(argv[0], argv, environ) < 0) {
printf("%s : Command not found\n\n", argv);
exit(0);
}
}
//addjob() 함수를 이용해서 joblist에 job을 추가한다
addjob(jobs, pid, (bg==1?BG:FG), cmdline);
if (!bg) { // foreground로 실행해야 한다면
waitpid(pid, NULL, 0); // 자식 프로세스가 종료될 때까지 대기
deletejob(jobs, pid); // 자식 프로세스 종료 후 job 에서 제거
} else {
printf("[%d] (%d) %s", pid2jid(pid), pid, cmdline);
//trace05가 요구하는 출력양식에 맞추어 출력
//pid2jid() 함수를 이용해서 양식에 맞추어 출력
}
};
return;
}
Trace 06 는 Background job 하나와 Foreground job 하나를 동시에 실행시키는 문제입니다. 먼저 trace06.txt 파일을 확인해보겠습니다.
myspin1 을 background 로 실행시키고 myspin2 를 argument 1과 함께 foreground job 으로 실행시키는 것을 확인할 수 있습니다.
Trace 05 에서 background 로 프로세스를 실행시키는 것을 잘 정의했으면 Trace 06 는 자동으로 통과합니다.