유닉스의 Shell 프로그램을 구현
1. 구현기능
- 좀비프로세스 방지
접기
//자식이 죽으면 보내는 SIGCHILD 시그널의 처리를 통해 좀비프로세스 방지
struct
sigaction act;
memset(&act, 0, sizeof(act));
act.sa_sigaction = sig_handler;
act.sa_flags = SA_SIGINFO | SA_RESTART;
sigaddset(&act.sa_mask, SIGCHLD);
sigaction(SIGCHLD, &act, 0);
//SIGCHLD 핸들러
void sig_handler(int sig, siginfo_t *siginfo, void* param2){
waitpid(siginfo->si_pid, NULL, 0);
}
- Foreground & Background 기능 구현
접기
명령어 마지막에 '&' 문자를 통해 Background 프로세스 판별
- exit 명령어로 shell 종료
- cd 명령어 구현
접기
if(!strnicmp(cmdgrp_list[0], cdCmd, 2)) { //cd 수행 memset(changedDir, '\0', 200); //디렉터리 변수 초기화 makelist(cmdgrp_list[0], " ", cdCmd_list, MAX_LIST); if(cdCmd_list[1] != NULL) { if(!strcmp(cdCmd_list[1], "/")) //root 디렉터리인 경우 strcat(changedDir, "/"); else { getcwd(changedDir, 200); //현재 디렉터리 + 인자로 받은 디렉터리 if(strcmp(changedDir, "/")) strcat(changedDir, "/"); strcat(changedDir, cdCmd_list[1]); } if( chdir(changedDir) ) { perror("error"); } }
}
- Redirection 처리
접기
void parse_redirection(char **cmd_args) { int i = 0, j = 0; int fd; for (i = 0; cmd_args[i]; i++){ if(!strcmp(cmd_args[i], ">")) { //stdout fd = open(cmd_args[i + 1], O_WRONLY | O_CREAT | O_TRUNC, 0644); if(fd == -1) { perror(cmd_args[i+1]); exit(1); } if( dup2(fd, STDOUT_FILENO) == -1 ) perror("Can't duplicate fd to STDOUT_FILENO"); close(fd); cmd_args[i] = NULL; } else if(!strcmp(cmd_args[i], "<")) { //stdin fd = open(cmd_args[i + 1], O_RDONLY); if(fd == -1) { perror(cmd_args[i+1]); exit(1); } if( dup2(fd, STDIN_FILENO) == -1 ) perror("Can't duplicate fd to STDIN_FILENO"); close(fd); cmd_args[i] = NULL; } } }
- shell 자체는 제어키 무시
접기
//ctrl + c, z 등의 signal 무시
signal(SIGQUIT, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
signal(SIGINT, SIG_IGN);
- Pipe 기능 구현
접기
void execute_grp(char* cmdgrp) { // 최초인풋 = ls -l | cat | wc -l ; ps // 1. cmdgrp = ls -l | cat | wc -l 첫 번째 자식 // 2. cmdgrp = ps 두 번째 자식 int cnt = 0; int i = 0; int p[2]; cnt = makelist(cmdgrp, "|", cmd_list, MAX_LIST); // 1. cmd_list[0] = "ls -l", [1] = " cat", [2] = " wc -l" // 2. cmd_list[0] = "ps" //wc -l 실행할 프로세스는 이거 자신이므로 cat 과 ls -1 프로세스만 만들면 되므로 cnt - 1로 설정 for(i=0; i<cnt-1; i++){ //1회전- 부모: ls -l 실행, 자식: Redirection //2회전- 부모: cat 실행, 자식: Redirection //2회전 후- wc -l 실행 (for문 후 마지막 execute_cmd) pipe(p); switch(fork()) { default: dup2(p[1], 1); //write—>STDOUT 연결 close(p[0]); close(p[1]); execute_cmd(cmd_list[i]); case 0: dup2(p[0], STDIN_FILENO); //read—>STDIN 연결 close(p[0]); close(p[1]); break; case -1: fatal("fork err"); } } execute_cmd(cmd_list[i]); }
2. 소스코드
댓글 없음:
댓글 쓰기