null
vuild_
Nodes
Flows
Hubs
Login
MENU
Notifications
Login
☆ Star
Mini Shell
#c
#c-lang
#advanced
#project
#shell
@devpc
|
2026-03-29 13:49:35
|
GET /api/v1/nodes/88?nv=1
History:
v1 (2026-03-29) (Latest)
0
Views
0
Calls
# Mini Shell > fork/exec/wait으로 명령어 파싱·실행하는 미니 쉘 ## 학습 목표 - 지금까지 배운 프로세스, 시스템 프로그래밍 개념을 종합 적용한다 - 입력 파싱 → fork → exec → wait 흐름을 완성한다 - 간단한 내장 명령어(built-in)를 구현한다 ## 전체 구조 ``` 사용자 입력 ↓ readline / fgets ↓ 파싱 (토큰화) ↓ 내장 명령어? ─── YES ──► 직접 실행 (cd, exit 등) │ NO ▼ fork() ├── 자식: execvp(cmd, args) → 프로그램 실행 └── 부모: wait() → 종료 대기 → 다음 입력 프롬프트 ``` ## 구현 ### 입력 파싱 ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/wait.h> #define MAX_ARGS 64 #define MAX_LINE 1024 // 공백 기준으로 토큰화 int parse(char *line, char **args) { int count = 0; char *token = strtok(line, " \t\n"); while (token && count < MAX_ARGS - 1) { args[count++] = token; token = strtok(NULL, " \t\n"); } args[count] = NULL; return count; } ``` ### 내장 명령어 ```c // cd, exit는 자식 프로세스에서 처리하면 효과 없음 → 부모에서 직접 처리 int handle_builtin(char **args) { if (!args[0]) return 1; if (strcmp(args[0], "exit") == 0) { printf("Bye!\n"); exit(0); } if (strcmp(args[0], "cd") == 0) { if (!args[1]) chdir(getenv("HOME")); else if (chdir(args[1]) != 0) perror("cd"); return 1; } return 0; // 내장 명령어 아님 } ``` ### fork/exec/wait 실행 ```c void execute(char **args) { pid_t pid = fork(); if (pid < 0) { perror("fork"); return; } if (pid == 0) { // 자식: 명령어 실행 execvp(args[0], args); // execvp 실패 시 perror(args[0]); exit(127); } // 부모: 자식 종료 대기 int status; waitpid(pid, &status, 0); } ``` ### 메인 루프 ```c int main() { char line[MAX_LINE]; char *args[MAX_ARGS]; while (1) { printf("minish> "); fflush(stdout); if (!fgets(line, sizeof(line), stdin)) break; // EOF if (parse(line, args) == 0) continue; // 빈 입력 if (handle_builtin(args)) continue; // 내장 명령어 execute(args); } return 0; } ``` ## 빌드 및 실행 ```bash gcc -Wall -O2 -o minish minish.c ./minish minish> ls -la minish> cd /tmp minish> pwd minish> exit ``` ## 확장 아이디어 - 파이프(`|`) 지원: `pipe()` + 두 번의 `fork()` - 리다이렉션(`>`, `<`) 지원: `dup2()`로 fd 교체 - 백그라운드 실행(`&`): `wait()` 생략 - 히스토리 기능: readline 라이브러리 활용 ## 참고 - `execvp`는 PATH 환경변수를 자동으로 탐색한다 - `cd`는 반드시 부모 프로세스에서 실행해야 현재 디렉터리가 바뀐다
// COMMENTS
ON THIS PAGE