셸 을 이해 하 는 좋 은 방법 배우 기 - 자신의 셸 을 만 드 는 2
6892 단어 clinuxshell시스템 프로 그래 밍
1. 제어
앞의 조건 이 만족 한 후에 무엇 을 합 니까?불만족
2. 변수
c = a + b 는 한 가지 형식 으로 다른 형식 을 대표 하 는데 바로 변수 입 니 다.형식 이 다 르 기 때문에 변 하지 않 는 것 으로 다른 변 화 를 나 타 낼 수 있다.예 를 들 어 '프로 그래 밍 언어' 는 하나의 변수 가 될 수 있 고 'C 언어', 'Perl 언어', 'Lisp' 언어 등 으로 값 을 부여 할 수 있다.변 수 는 완충 사상 으로 이해 할 수 있 습 니 다. 한 컵 은 물 한 잔, 주스 한 잔, 술 한 잔 을 잠시 저장 할 수 있 습 니 다. 이 세 가지 이름 은 '액체' 라 는 변수 이름 으로 분류 할 수 있 습 니 다.
3. 환경
사실 백 마 는 말 에 속 하고 환경 도 변수의 일종 이다.다만 이 는 일반적으로 시스템 이 제공 하 는 것 으로 소프트웨어 가 실 행 될 때마다 변 수 를 설정 하 는 번 거 로 움 을 피하 기 위해 서 이다. 예 를 들 어 언어 를 설정 하 는 등 환경 이 있 으 면 바로 이런 변 수 를 사용 할 수 있다.일반적인 PATH, HOME. 명령 env 는 시스템 의 환경 변 수 를 볼 수 있 습 니 다.
우선 명령 행 분석 을 추가 하여 사용자 가 한 줄 에 명령 과 인 자 를 입력 할 수 있 도록 해 야 합 니 다.해상도 기 는 입력 한 줄 을 문자열 배열 로 나 누 어 하위 프로 세 스 의 execvp 에 전달 합 니 다.
신호 얘 기 좀 하 자.신 호 는 하나의 단어 로 구 성 된 메시지 로 프로 세 스 간 통신 에 사 용 됩 니 다. 프로 세 스 가 열심히 달리 고 있 습 니 다. 말 을 걸 려 면 종료, 정지 시 키 려 면 신 호 를 사용 해 야 합 니 다.kill - l 신호 목록 을 볼 수 있 습 니 다.
프로 세 스 처리 신 호 는 세 가지 상황 이 있 습 니 다. 하 나 는 기본 처리 이 고 보통 소멸 합 니 다. 이 호출 signal (SIGINT, SIG DFL) 은 SIGINT 의 기본 처 리 를 복원 합 니 다.둘째, 이 호출 signal (SIGINT, SIG IGN) 을 무시 합 니 다.셋째, 함수 signal (signum, function) 을 호출 합 니 다.
2) SIGINT 프로그램 종료 (interrupt) 신 호 는 사용자 가 INTR 문자 (보통 Ctrl - C) 를 입력 했 을 때 보 냅 니 다. 프론트 프로 세 스 그룹 에 프로 세 스 종 료 를 알 리 는 데 사 용 됩 니 다.
3) SIGQUIT
SIGINT 와 유사 합 니 다. QUIT 문자 (보통 Ctrl - \) 로 제어 합 니 다. 프로 세 스 는 SIGQUIT 가 종료 되 었 을 때 core (핵 토 출) 파일 을 생 성 합 니 다.
20) SIGTSTP
프로 세 스 실행 을 중지 하지만 이 신 호 는 처리 되 고 무시 할 수 있 습 니 다. 사용자 가 SUSP 문 자 를 입력 했 을 때 (보통 Ctrl - Z) 이 신 호 를 보 냅 니 다.
이 셸 에 서 는 SIGINT 와 SIGQUIT 를 처리 합 니 다. 셸 에 서 는 두 가 지 를 무시 하지만 하위 셸 에 서 는 기본 동작 을 복원 합 니 다. 셸 에서 하위 프로 세 스 를 끝 낼 수 있 기 때문에 셸 을 스스로 죽 이지 않 습 니 다.
셸 의 main 함 수 는 다음 과 같 습 니 다.
/* chicken_sh.c
* , .
* , egg_sh
*/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
#include "smsh.h"
#define DFL_PROMPT "> "
void setup();
void fatal(char *s1, char *s2, int n)
int main()
{
char *cmdline, *prompt, **arglist;
int result;
prompt = DFL_PROMPT;
setup();
while ((cmdline = next_cmd(prompt, stdin)) != NULL) {
if ((arglist = splitline(cmdline)) != NULL) {
result = execute(arglist);
freelist(arglist);
}
free(cmdline);
}
return 0;
}
void setup()
/*
*/
{
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
}
void fatal(char *s1, char *s2, int n)
/*
*/
{
fprintf(stderr, "Error: %s, %s
", s1, s2);
exit(n);
}
함수 설명:
next_cmd 입력 에서 다음 명령 을 읽 고, 임의의 길이 파 라미 터 를 받 아들 이기 위해 malloc 로 메모 리 를 분배 합 니 다. 파일 이 끝나 면 NULL 로 돌아 갑 니 다.
splitline 파 라 메 터 를 분석 합 니 다. 문자열 을 문자열 배열 로 분해 하고 이 배열 로 되 돌려 줍 니 다.
chicken_sh 는 비교적 복잡 하기 때문에 코드 는 세 개의 파일 로 나 뉜 다. chickensh.c, splitline.c, execute.c .(원본 다운로드)
이렇게 컴 파일:
gcc -o chichen_sh chicken_sh.c splitline.c execute.c
그 중의 execute. c 는 변화 가 크 지 않 고 신호 처리 만 증가 했다.
splitline. c 는 좀 복잡 합 니 다. 설명 이 필요 합 니 다. 코드 는 다음 과 같 습 니 다.
/*splitline.c
* chicken_sh
*char *next_cmd(char *prompt, FILE *fp)
*char **splitline(char *str);
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "chicken_sh.h"
char *next_cmd(char *prompt, FILE * fp)
{
char *buf;
int bufspace = 0;
int pos=0; /* */
int c;
printf("%s", prompt);
while ((c = getc(fp)) != EOF) {
/* */
if (pos + 1 >= bufspace) {
if (bufspace == 0)
buf = emalloc(BUFSIZ);
else
buf = erealloc(buf, bufspace + BUFSIZ); /* */
bufspace += BUFSIZ;
}
/* */
if (c == '
')
break;
/* , */
buf[pos++] = c;
}
if (c == EOF && pos == 0)
return NULL;
buf[pos] = '\0';
return buf;
}
#define is_delim(x) ((x) == ' ' || (x) == '\t') /* tab*/
char *newstr(char *s, int l);
char **splitline(char *line)
{
char **args; /* */
int spots = 0; /* */
int bufspace = 0; /* */
int argnum = 0; /* */
char *cp = line;
char *start;
int len;
if (line == NULL) /* */
return NULL;
args = emalloc(BUFSIZ); /* */
bufspace = BUFSIZ;
spots = BUFSIZ / sizeof(char *);
while (*cp != '\0') {
while (is_delim(*cp))
cp++;
if (*cp == "\0")
break;
/* */
if (argnum + 1 >= spots) {
args = erealloc(args, bufspace + BUFSIZ);
bufspace += BUFSIZ;
spots += (BUFSIZ / sizeof(char *));
}
/* , \0 */
start = cp;
len = 1;
while (*++cp != '\0' && !(is_delim(*cp)))
len++;
args[argnum++] = newstr(start, len);
}
args[argnum] = NULL;
return args;
}
/*
* , '\0' */
char *newstr(char *s, int l)
{
char *rv = emalloc(l + 1);
rv[l] = '\0';
strncpy(rv, s, l);
return rv;
}
void freelist(char **list)
/* , */
{
char **cp = list;
while (*cp)
free(*cp++);
free(list);
}
void *emalloc(size_t n)
{
void *rv;
if ((rv = malloc(n)) == NULL)
fatal("out of memory", "", 1);
return rv;
}
void *erealloc(void *p, size_t n)
{
void *rv;
if ((rv = realloc(p, n)) == NULL)
fatal("realloc() failed", "", 1);
return rv;
}
emalloc 와 erealloc 는 잘못된 처 리 된 분배 공간 을 봉인 하 는 함수 입 니 다.
next_cmd 는 사용자 가 입력 한 명령 과 파 라 메 터 를 받 아들 여 링크 에 저장 합 니 다.
splitline 은 받 아들 인 매개 변 수 를 매개 변수 로 나 누 는 포인터 배열 을 담당 합 니 다. 공간 은 모두 동적 으로 분 배 됩 니 다. 사용자 가 명령 을 입력 할 때 각 매개 변 수 는 빈 칸 이나 tab 로 분리 되 어 있 기 때 문 입 니 다. newstr 는 그들 을 문자 독립 된 문자열 로 나 누 어 '\ 0' 으로 끝 냅 니 다.
컴 파일 된 chickensh, 일반 명령 을 실행 하 는 것 은 정상 셸 과 다 르 지 않 으 며, ctrl + D 를 누 르 면 종료 할 수 있 습 니 다.그리고 이 몇 가지 개선 도 할 수 있다.
1. 한 줄 에 여러 개의 명령 을 분점 으로 구분한다.
2. 백 스테이지 프로 세 스, 즉 명령 마지막 에 '&' 를 추가 합 니 다.
3. exit 명령 으로 종료 할 수 있 습 니 다. 종료 코드 를 설정 할 수 있 습 니 다. exit 1, exit 0 과 같 습 니 다.
다음 에 if. then 제어 문 구 를 추가 합 니 다.
셸 의 if 와 C 의 if 는 다른 점 이 있 습 니 다. C 에서 if 는 그 뒤의 문장 이나 괄호 로 싸 인 문장 블록 에 작용 하고 셸 은 then 으로 시작 합 니 다. "fi" 로 if 의 끝 을 표시 하면 실행 중인 프로 세 스 디자인 을 설명 하 는 데 간단 합 니 다.
그리고 if 는 명령 을 바탕 으로 0 으로 종료 하 는 것 이 성공 적 이라는 가설 입 니 다. 예 를 들 어:
if cat hello.c
then
echo hello
fi
cat 명령 이 성공 적 으로 실행 되 고 0 으로 돌아 가면 then 에서 fi 의 구문 블록 이 실 행 됩 니 다.명령 반환 0 과 if 뒤에서 0 을 직접 두 드 리 는 것 은 다 릅 니 다. 진 위 를 직접 설명 하려 면 true 와 false 를 사용 할 수 있 습 니 다. if true 는 if 뒤에서 성공 적 인 명령 을 수행 한 것 과 같 습 니 다. false 는 반대 입 니 다.
너무 길 어 요. 다음 편 에 쓰 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Docker를 사용한 React 및 .NET Core 6.0 샘플 프로젝트 - 1부이 기사에서는 Entity Framework Core Code First 접근 방식을 사용하는 ASP.NET Core 6.0 WEP API의 CRUD(만들기, 읽기, 업데이트 및 삭제) 작업에 대해 설명합니다. 웹 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.