[유 닉 스 / 리 눅 스 프로 그래 밍 실천] 셸 은 프로그램 을 어떻게 실행 합 니까 - 명령 해석 기 를 작성 합 니 다 sh
17598 단어 shellbashLinux 프로 그래 밍
셸 은 아래 순환 으로 구성 되 어 있 습 니 다:
while (!end_of_input)
getcommand
execute command
wait for command to finish
우 리 는 실제로 셸 을 사용 할 수 있다.
jiange@jiange-Inspiron:~/cpp$ ls
override override.cpp test test1.cpp test.cpp test.o test.sh
jiange@jiange-Inspiron:~/cpp$ ps
PID TTY TIME CMD
2457 pts/12 00:00:00 bash
3780 pts/12 00:00:00 ps
상기 과정 은:
sh 는 ls 를 읽 고 프로 세 스 ls 를 새로 만 들 고 실행 합 니 다. 이때 sh 는 ls 가 종료 되 기 를 기다 리 고 ls 가 종료 되면 sh 로 돌아 가 sh 는 ps 를 계속 읽 습 니 다.
따라서 sh 를 만 들 려 면 프로그램 을 실행 하 는 방법, 생 성, 프로 세 스 종료, 그리고 프로 세 스 가 다른 프로 세 스 의 끝 을 기다 리 는 방법 을 알 아야 합 니 다.
2. 프로그램 을 어떻게 실행 합 니까?
답:
execvp(progname, arglist)
그것 의 운영 절차:
ls 를 실행 하 는 예:
/* exec1.c - shows how easy it is for a program to run a program
*/
main()
{
char *arglist[3];
arglist[0] = "ls";
arglist[1] = "-l";
arglist[2] = 0 ;
printf("* * * About to exec ls -l
");
execvp( "ls" , arglist );
printf("* * * ls is done. bye
");
}
실행 결과:
$ ./exec1
* * * About to exec ls -l
40
-rwxrwxr-x 1 jiange jiange 7370 12 7 22:59 exec1
-rw-rw-r-- 1 jiange jiange 262 10 14 2007 exec1.c
-rw-rw-r-- 1 jiange jiange 406 10 14 2007 forkdemo1.c
-rw-rw-r-- 1 jiange jiange 315 10 14 2007 forkdemo2.c
-rw-rw-r-- 1 jiange jiange 503 10 14 2007 forkdemo3.c
-rw-rw-r-- 1 jiange jiange 1395 10 14 2007 psh1.c
-rw-rw-r-- 1 jiange jiange 1766 10 14 2007 psh2.c
-rw-rw-r-- 1 jiange jiange 784 10 14 2007 waitdemo1.c
-rw-rw-r-- 1 jiange jiange 1077 10 14 2007 waitdemo2.c
모든 것 이 정상적으로 작 동 하 는 것 같 지만, 왜 printf ("* * ls is done. bye");이 한 마디 가 실행 되 지 않 았 는데?!
이 는 execvp 의 역할 을 이해 해 야 합 니 다. execvp 는 현재 프로 세 스 의 코드 와 데 이 터 를 디스크 에서 불 러 옵 니 다. 따라서 execvp 를 실행 한 후에 프로 세 스 exec 1 이 완전히 교체 되 어 후속 인쇄 작업 을 수행 하지 않 습 니 다.
2. 프롬프트 가 있 는 셸
이 버 전 은 사용자 에 게 프로그램 이름과 인 자 를 입력 하고 실행 하 라 고 알려 줍 니 다.
/* prompting shell version 1 * Prompts for the command and its arguments. * Builds the argument vector for the call to execvp. * Uses execvp(), and never returns. */
#include <stdio.h>
#include <signal.h>
#include <string.h>
#define MAXARGS 20 /* cmdline args */
#define ARGLEN 100 /* token length */
int main()
{
char *arglist[MAXARGS+1]; /* an array of ptrs */
int numargs; /* index into array */
char argbuf[ARGLEN]; /* read stuff here */
char *makestring(); /* malloc etc */
numargs = 0;
while ( numargs < MAXARGS )
{
printf("Arg[%d]? ", numargs);
if ( fgets(argbuf, ARGLEN, stdin) && *argbuf != '
' )
arglist[numargs++] = makestring(argbuf);
else
{
if ( numargs > 0 ){ /* any args? */
arglist[numargs]=NULL; /* close list */
execute( arglist ); /* do it */
numargs = 0; /* and reset */
}
}
}
return 0;
}
int execute( char *arglist[] )
/* * use execvp to do it */
{
execvp(arglist[0], arglist); /* do it */
perror("execvp failed");
exit(1);
}
char * makestring( char *buf )
/* * trim off newline and create storage for the string */
{
char *cp, *malloc();
buf[strlen(buf)-1] = '\0'; /* trim newline */
cp = malloc( strlen(buf)+1 ); /* get memory */
if ( cp == NULL ){ /* or die */
fprintf(stderr,"no memory
");
exit(1);
}
strcpy(cp, buf); /* copy chars */
return cp; /* return ptr */
}
문자열 매개 변 수 를 동적 으로 할당 하기 위해 makestring 함 수 를 사용 합 니 다.
위의 프로그램 을 실행 하면 우 리 는 파 라 메 터 를 전달 할 수 있다.
그러나 비교적 심각 한 결함: ls 를 실행 한 후에 전체 프로그램 이 종료 되 었 습 니 다. 우 리 는 ls 를 실행 한 후에 우리 의 셸 로 돌아 가 셸 은 명령 입력 을 계속 받 고 실행 할 수 있 기 를 기대 합 니 다.
처음에 우 리 는 sh 가 ls 를 읽 고 프로 세 스 ls 를 새로 만 들 고 실행 할 것 이 라 고 말 했 습 니 다. 이때 sh 는 ls 가 종료 되 기 를 기다 리 고 ls 가 종료 되면 sh 로 돌아 갑 니 다.
즉, sh 는 ls 명령 을 직접 실행 하지 않 고 프로 세 스 를 새로 만 들 었 습 니 다. 그러면 문제 가 생 겼 습 니 다. 어떻게 새로운 프로 세 스 를 만 듭 니까?
정 답: fork () 사용 하기;
하위 프로 세 스 를 만 들 기 위해 fork 를 사용 할 수 있 습 니 다. 그리고 새로운 프로 세 스 는 execvp 를 사용 하여 사용자 명령 을 수행 할 수 있 습 니 다.
그렇다면 부모 프로 세 스 sh 는 하위 프로 세 스 ls 의 끝 을 어떻게 기다 리 나 요?
정 답: pid = wait (& status) 사용 하기;
wait 는 하위 프로 세 스 가 끝 날 때 까지 프로 세 스 를 호출 하 는 것 을 막 고 wait 가 하위 프로 세 스 가 끝 날 때 exit 의 값 (status 를 통 해) 을 전달 하고 하위 프로 세 스 의 PID 를 되 돌려 줍 니 다.
3. 사용자 명령 을 계속 받 을 수 있 는 셸
이상 의 분석 을 통 해 우 리 는 새로운 셸 을 설계 할 수 있다.
명령 가 져 오기 - > fork 로 새 프로 세 스 만 들 기 - > 부모 프로 세 스 wait - > 하위 프로 세 스 exec 새 프로그램 실행 - > 새 프로그램 main 에서 실행 - > 새 프로그램 exit - > 부모 프로 세 스 가 하위 프로 세 스 상 태 를 가 져 옵 니 다 - > 명령 가 져 오기
/** prompting shell version 2 ** ** Solves the `one-shot' problem of version 1 ** Uses execvp(), but fork()s first so that the ** shell waits around to perform another command ** New problem: shell catches signals. Run vi, press ^c. **/
#include <stdio.h>
#include <signal.h>
#define MAXARGS 20 /* cmdline args */
#define ARGLEN 100 /* token length */
main()
{
char *arglist[MAXARGS+1]; /* an array of ptrs */
int numargs; /* index into array */
char argbuf[ARGLEN]; /* read stuff here */
char *makestring(); /* malloc etc */
numargs = 0;
while ( numargs < MAXARGS )
{
printf("Arg[%d]? ", numargs);
if ( fgets(argbuf, ARGLEN, stdin) && *argbuf != '
' )
arglist[numargs++] = makestring(argbuf);
else
{
if ( numargs > 0 ){ /* any args? */
arglist[numargs]=NULL; /* close list */
execute( arglist ); /* do it */
numargs = 0; /* and reset */
}
}
}
return 0;
}
execute( char *arglist[] )
/* * use fork and execvp and wait to do it */
{
int pid,exitstatus; /* of child */
pid = fork(); /* make new process */
switch( pid ){
case -1:
perror("fork failed");
exit(1);
case 0:
execvp(arglist[0], arglist); /* do it */
perror("execvp failed");
exit(1);
default:
while( wait(&exitstatus) != pid )
;
printf("child exited with status %d,%d
",
exitstatus>>8, exitstatus&0377);
}
}
char *makestring( char *buf )
/* * trim off newline and create storage for the string */
{
char *cp, *malloc();
buf[strlen(buf)-1] = '\0'; /* trim newline */
cp = malloc( strlen(buf)+1 ); /* get memory */
if ( cp == NULL ){ /* or die */
fprintf(stderr,"no memory
");
exit(1);
}
strcpy(cp, buf); /* copy chars */
return cp; /* return ptr */
}
형식 제어 에 있어 서, 예 를 들 어 한 줄 에 인 자 를 입력 하 는 방법, exit 로 셸 을 종료 하 는 방법 등 은 여기에서 우 리 는 토론 하지 않 습 니 다.
실행 할 때, 우 리 는 심각 한 오 류 를 발견 했다.
만약 우리 가 키 프로 세 스 를 실행 하고 있다 면, 이때 우 리 는 Ctrl - C 키 를 입력 합 니 다. 우 리 는 하위 프로 세 스 가 종료 되 어야 하 며, 셸 은 계속 실행 되 어야 합 니 다. 그러나 사실은 셸 도 종료 되 었 습 니 다. 키보드 신호 SIGINT 가 모든 연결 프로 세 스 를 보 냈 기 때 문 입 니 다!
하위 프로 세 스 가 실 행 될 때 셸 은 신 호 를 중단 했다 고 해서 종료 되 지 않 습 니 다. 하위 프로 세 스 가 실 행 될 경우 셸 은 SIGINT 신호 에 대한 응답 을 ignore 로 설정 하고 하위 프로 세 스 가 끝 난 후에 기본 방식 으로 설정 합 니 다.이렇게 하면 셸 은 하위 프로 세 스 가 실 행 될 때 중단 신 호 를 차단 할 수 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
ZSH에서 물고기까지ZSH는 수년 동안 내 기본 셸이었습니다. 이제 몇 달 동안 사용하면서 ZSH 구성에 대해 몇 가지 사항을 발견했습니다. 우리는 을 제공하는 시스템과 더 빨리 상호 작용하는 경향이 있습니다. 내.zshrc 구성에는 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.