리눅스 쉘 프로그래밍 보고서 1 날짜 : 2019.11.07 박제현
-
요구사항 1)cd 명령어가 제대로 실행되도록 수정 2)exit 명령을 구현 3)백그라운드 실행을 구현
-
Background 명령어
Main 함수에서는 입력된 명령어가 background로 실행되는지 foreground로 실행되는지 판별하기 위해서 입력 받은 문자열에 대해 & 가 포함되어 있는지 한 글자씩 검색한 후, 만약 &가 있다면 초기값이 0인 int background변수를 1로 바꿔 background로 실행되어야 하는 명령어임을 표시해주고, 해당 & 문자를 \0으로 바꿔 줍니다. 이후 makelist함수를 실행해 cmdvector를 맞게 생성합니다.
이후 fork()가 일어나게 되면 부모 프로세스는 switch 문에서 background가 0인 경우, 즉 background 프로세스가 아닌 경우만 waitpid함수로 자식 프로세스가 종료되기를 기다리고, background 프로세스인 경우에는 부모 프로세스가 자식 프로세스를 기다리지 않고 바로 실행될 수 있도록 합니다. sleep 10 &를 실행하면 기다리지 않고 바로 쉘프롬프트가 출력됩니다. 또한, sleep 10을 실행하면 쉘프롬프트가 10초 후에 출력됩니다.
[고찰] 좀비 프로세스가 생기는 이유는 background 프로세스 실행 시 부모 프로세스가 자식 프로세스를 wait하지 않기 때문입니다. 자식 프로세스가 종료되어도 부모 프로세스가 적절히 처리해주지 못하기 때문에 좀비 프로세스로 계속 남아있게 됩니다.
[고찰]위의 고찰에서처럼, 백그라운드로 실행되는 명령들은 실행이 끝나도 종료되지 못하고 좀비 프로세스로 남아 메모리를 낭비한다는 문제점이 있습니다. 백그라운드 프로세스를 다른 부모 프로세스의 자식 프로세스로 넘겨서 이 프로세스가 실행이 끝나면 정상적으로 종료될 수 있도록 해 문제를 해결할 수 있습니다.
- cd 명령어 & exit 명령어
기존 코드에서 cd명령어가 정상적으로 실행되지 않았던 이유는 switch 문에서 fork()가 발생하고 이때 생성된 자식 프로세스가 cd 명령어를 실행시키기 때문에 부모 프로세스인 myshell은 영향을 받지 않기 때문입니다. 따라서, cd 명령어가 정상적으로 동작하도록 하기 위해서는 이 이 명령어가 부모 프로세스에서 동작하도록 수정해 주어야 합니다. 따라서, 저는 cd 명령어가 저장되어 있을 수 있는 cmdvector[0]을 검사하여 cd 가 저장되어 있다면 자식 프로세스를 생성하지 않고 바로 chdir 함수를 실행하여 부모 프로세스에서 cd 명령어가 실행될 수 있도록 합니다. Exit 명령어 또한 같은 이유로 정상적으로 실행되지 않기 때문에, 같은 방법을 이용해 부모 프로세스에서 exit(0) 함수가 실행될 수 있도록 수정해 주면 cd 명령어와 exit 명령어가 정상 작동합니다.
리눅스 쉘 프로그래밍 보고서 2 날짜 : 2019.11.14. 박제현
-
요구사항 1)SIGCHLD로 자식 프로세스 wait() 시 프로세스가 온전하게 수행 2)SIGINT, SIGQUIT 사용시 쉘이 종료되지 않음 3)Forground 프로세스 실행 시 SIGINT를 받으면 프로세스가 종료
-
SIGCHLD로 자식 프로세스 wait()시 프로세스가 온전하게 수행 자식 프로세스가 background 명령을 실행하고 나면 이때 fork된 자식 프로세스가 SIGCHLD 시그널을 부모 프로세스에게 보내지만 이 때 부모 프로세스가 자식 프로세스를 wait하지 않기 때문에 수행이 끝난 자식 프로세스가 종료되지 못하고 좀비 프로세스로 남게 됩니다. Signal(SIGCHLD, SIG_IGN);를 사용하면 이런 문제가 해결되어 자식 프로세스가 실행이 끝나면 부모 프로세스가 자식프로세스를 종료시켜 좀비 프로세스가 생기는 문제를 해결할 수 있습니다. sleep 50이 sleep 20 &과 sleep 30 &에 방해받지 않고 잘 수행되는 것을 확인할 수 있으며 좀비 프로세스도 남지 않는 것을 확인할 수 있습니다.
-
SIGINT, SIGQUIT 사용시 쉘이 종료되지 않도록 수정
main함수에서 myshell 실행 시에 Ctrl+C나 Ctrl+\를 누를 때 쉘이 종료되지 않도록 합니다. Ctrl+C를 누르면 SIGINT가 발생하고, Ctrl+\를 누르면 SIGQUIT이 발생하기 때문에 main함수 내부에 다음과 같이 signal함수를 이용해 이 시그널들이 무시될 수 있도록 합니다.
위와 같이 코드를 수정하면 SIGINT, SIGQUIT, SIGCHLD 시그널을 받았을 때 이 신호들을 무시합니다. 따라서, 쉘이 종료되지 않고 계속 실행되도록 할 수 있습니다. 3. Forground 프로세스 실행 시 SIGINT를 받으면 프로세스가 종료 자식 프로세스가 fork되면 이 프로세스 또한 부모 프로세스처럼 SIGINT를 무시합니다. 따라서, 이 프로세스가 execvp함수를 사용해 명령어를 수행하기 전에 다음과 같이 초기화 해주면 자식 프로세스는 정상적으로 SIGINT를 사용해 시그널로 프로세스를 종료시킬 수 있습니다.
명령어 수행 시에 SIGINT가 발생하면 수행중인 명령이 중단되는 것을 확인할 수 있습니다.
리눅스 쉘 프로그래밍 보고서 3 날짜 : 2019.11.22. 박제현
-
요구사항 1)Redirection 구현
-
Redirection 구현 Redirection을 구현하기 위해 main 함수에서 makelist 함수로 cmdvector가 생성되면, redirectionCheck함수를 통해 < 또는 > 가 cmdvector에 포함되어 있는지 확인한 후, 벡터의 이 부분은 null 문자로 바꿔준 후, < 또는 > 다음 벡터에 저장되어 있는 파일명을 filename char 배열에 저장합니다. 이 filename을 이용해 파일을 열거나 새로 생성합니다. 그 다음에 dup2 함수를 사용해 < 일 경우 표준 입력을 파일로 바꾸거나 > 일 경우 표준 출력을 파일로 바꿔줍니다. 또한, 백그라운드 프로세스일 경우 &을 따로 분리한 후 부모 프로세스가 자식 프로세스를 wait 하지 않게 함으로써 백그라운드에서도 정상 작동하도록 구현하였습니다.