C实现一个简单Shell
2024-04-22 23:00:45

1. Shell运行的基本逻辑

Shell一般按照如下的步骤运行:等待状态-获取命令行输入-处理-创建子进程-等待子进程运行结束-等待状态。

分别来说:

  1. 获取命令行输入可以使用readline(),scanf()之类的函数。
  2. 处理输入,首先要做的是将输入按照分隔符分开,得到一个二维数组。接着,我们要对获得的命令进行判断,判断其是否为内置命令,如果为内置命令,需要执行我们自己编写函数,如果不是内置命令,就要通过fork()创建一个子进程,在子进程中执行非内置命令,父进程等待子进程的结束。

2. 获取输入

读取输入的函数大概如下,一个字符一个字符读取,方便我们控制对应的行为,比如读取到EOF就直接返回等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int ReadLine(char* buffer) {
int buffer_pivot = 0;

while(1) {
if(buffer_pivot == BUFFER_SIZE) {
printf("The expression is too long to process.\n");
return ERR_EXPR_TOO_LONG;
}

char current_char = getchar();
if(current_char == '\n') {
buffer[buffer_pivot++] = '\0';
break;
} else if(current_char == EOF){
return INPUT_EOF;
} else {
buffer[buffer_pivot++] = current_char;
}
}

return strlen(buffer);
}

3. 处理输入

使用strtok()函数,可以将字符串根据设定的分隔符,分割成各部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
char** ProcessLine(char* command) {
char** command_tokens = (char**)SafeMalloc(sizeof(char) * BUFFER_SIZE);
char* token;
int command_tokens_index = 0;

token = strtok(command, TOKEN_DELIMITER);
while(token != NULL) {
command_tokens[command_tokens_index++] = token;
token = strtok(NULL, TOKEN_DELIMITER);
}

command_tokens[command_tokens_index] = NULL;
return command_tokens;
}

4. 进程处理

大致如此。之前CSAPP的课设里,执行程序使用的是execve(),用execvp()倒也无所谓,它们的功能都差不多。exec函数族属于”进程替换”的函数族,执行它们不创建新进程,而是将当前进程覆盖掉,执行要执行的程序,这也是我们要创建子进程执行命令的原因。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int ExecuteCommand(char **token_list) {
pid_t command_pid;
int status = 0;
if(token_list[0] == NULL) {
return SUCCESS;
} else {if(strcmp(token_list[0], "cd") == 0) {
return Command_cd(token_list);
} else if(strcmp(token_list[0], "exit") == 0) {
return Command_exit(token_list);
}
}
command_pid = fork();
if(command_pid == 0) {
if(execvp(token_list[0], token_list) == -1) {
perror("Execute Error");
exit(0);
return ERR_FAILED_TO_EXEC;
}
} else if(command_pid > 0) {
wait(&status);
} else {
perror("Fork Error");
exit(0);
}
free(token_list);
return SUCCESS;
}
Prev
2024-04-22 23:00:45
Next