-
my shell 프로젝트(개인)프로젝트 2022. 7. 4. 19:46728x90
이번 학기 시스템 프로그래밍 수업을 들으면서 처음으로 개발 이라는 프로젝트에 도전하였습니다.
리눅스 환경에 있는 shell을 직접 구현하는 것입니다.
총 3개의 Phase로 구성되어 있습니다.
리눅스 환경을 다루는 것도 처음이고 리눅스 명령어도 모르며 리눅스 shell 안에서 vi 에디터로 코딩하는 것도
처음이었기에 첫걸음이 매우 오래 걸렸습니다...
구글의 도움을 받아 리눅스 명령어 부터 익히고 (ex : ls, pwd, cd, 등등) 리눅스 shell 안에서 코딩하는 법(vi 에디터)
를 배우며 점점 익숙해져갔습니다.
하지만 vi 에디터로 코딩을 하는 것은 아직 많이 익숙하지 않아 vscode를 이용해 ssh 원격 접속을 통해 코딩을
진행하였습니다.
대충 프로젝트를 진행할 환경은 구축해 놓았지만 shell을 구현하는데 어떤 것을 먼저 시작할지 감이 안잡혔습니다.
처음에는 shell에 대한 기초지식도 없었습니다.
예를 들어 user가 ls 명령어를 입력하면 현재 경로에 있는 디렉토리나 파일을 모두 보여줘야 하는데
이를 모두 반복문으로 구현하는 줄 알았습니다. 즉, 정말로 머리속에는 아무것도 들어있지 않았습니다.
이제 부터 phase 마다 접근 방법을 기록해보겠습니다.
Phase 1
그냥 단순한 shell 기능만 갖추고 있는 shell을 구현하는 것입니다.
저는 지금까지 window환경에서 편하게 visual studio라는 에디터로 알고리즘 문제를 풀거나 학교 과제를 하곤
했습니다.
따라서 대부분은 하나의 main 파일 안에 모든 함수나 전역변수를 입력해 사용해왔습니다.
하지만 함수들이 많아지면 하나의 main 파일에 모두 기입하는것이 어려울 수 있습니다.
나중에 배울 Linking 이라는 개념에서도 나오겠지만 하나의 실행파일을 만들기 위해서는
컴파일과 어셈블러를 거쳐 완성된 object 파일들과 헤더 파일들이 하나로 묶여서 만들어 집니다..
따라서 main 파일 따로 각각의 함수 파일을 따로 만들어서 마지막에 Linking으로 묶어주기만 하면 됩니다.
main
먼저 main 파일입니다.
1번째 줄에 있는 헤더파일 "myshell.h"는 제가 직접 만든 헤더 파일입니다. (나중에 설명)
먼저 제가 생각한것은 무엇이 됐든 명령어를 입력받아야 하는 것입니다.
따라서 cmdline이라는 문자열을 만들어 readline이라는 함수로 입력을 받았습니다.
명령어를 입력받은 cmdline은 eval 함수에 의해 실행해 줍니다.
readline
char * 형으로 return 해주는 함수입니다.
먼저 입력 받는 buffer의 크기는 1024 byte로 설정해주었습니다.
position변수는 문자가 들어갈 자리를 나타내는 pointer 역할을 해줍니다.
buffer라는 char * 형 변수에다가 malloc 함수를 이용해 1024의 크기만큼 동적할당을 진행하였습니다.
34번째 줄부터 입력을 받고 buffer에 저장해 return 해줍니다.
문자열의 마지막에는 \n 이 들어가므로 마지막 위치에대가 넣어주고 return합니다.
eval
명령어를 실행하는 eval 함수입니다.
예를 들어 명령어가 ls -al 같이 들어오게 되면 명령어를 ls, -al 이렇게 2개로 쪼개야 합니다.
이를 위해 문자열 배열인 char **argv를 선언합니다.
33번째 줄인 builtin_command 함수는 입력된 명령어가 exit, cd, help등등 인지 확인합니다.
만약 builtin_command가 true이면 일반적인 명령어고 false이면 exit, cd, help 인것입니다.
이제 34번째 줄부터는 fork 함수를 통해 child process를 생성할 것입니다.
exec 계열의 함수는 하나의 process를 실행하다가 다른 process를 실행하여 현재 process를 무시하고 새로운
process를 실행하는 함수입니다.
자식 process가 argv에 넣어둔 명령어를 실행하는 동안 부모 process는 wait 함수를 통해 기다리다가
자식 process가 일을 마치고 exit되는 순간 다시 부모 process가 움직입니다.
parseline
명령어를 쪼개주는 함수입니다.
예를 들어 명령어가 ls -al로 들어오면 argv[0] = ls, argv[1] = -al 이렇게 쪼개져야 합니다.
strtok를 이용해 구현하였습니다.
builtin_command
만약 명령어가 exit 이라면 바로 exit 함수를 실행시켜 끝냅니다.
우리가 흔히 사용하는 cd 명령어는 chdir함수로 구현되어 있습니다.
따라서 chdir함수를 사용해 cd 명령어를 구현하였습니다.