整个程序运行分为四部分:
-
- 写一个shell的入口,用于提示要输入信息
-
- scanf接收一个输入信息
-
- 创建子进程
-
- 程序替换
输入信息:
- 程序替换
printf("minishell: ");
fflush(stdout);
char cmd[1024] = {0};
if (scanf("%[^\n]%*c", cmd) != 1) {
getchar();
}
^\n:scanf本身是遇到空格就要获取一次,这样的话就无法获取
到一个完整的命令,因此‘%[^\n]’表示的是获取数据直到遇到\n为止
%*c:将缓冲区中的字符都取出来,但是不要它,直接丢掉
目的是为了将最后的\n从缓冲区取出来,防止陷入死循环
解析获得的命令:
在char *ptr = cmd;
char *argv[32] = {NULL};
int argc = 0;
argv[argc++] = ptr;
while(*ptr != '\0') {
int isspace(int c);
//用于判断一个字符是否是:\t \n \r 空格
//解析一个字符串时候这里就是对空格的判断
if (isspace(*ptr)) {
while(isspace(*ptr) && *ptr != '\0') {
*ptr++ = '\0';
}
argv[argc++] = ptr;
}
ptr++;
}
if (fork() == 0) {
execvp(argv[0], argv);
}
子进程创建程序替换:
if (fork() == 0) {
execvp(argv[0], argv);
}
wait(NULL);
需要等待的原因:
1. 避免产生僵尸子进程
2. 是为了等待子进程运行完毕,让程序逻辑更加完善
完整版程序实现如下:
int main()
{
while(1) {
printf("minishell: ");
fflush(stdout);
char cmd[1024] = {0};
if (scanf("%[^\n]%*c", cmd) != 1) {
getchar();
}
char *ptr = cmd;
char *argv[32] = {NULL};
int argc = 0;
argv[argc++] = ptr;
while(*ptr != '\0') {
if (isspace(*ptr)) {
while(isspace(*ptr) && *ptr != '\0') {
*ptr++ = '\0';
}
argv[argc++] = ptr;
}
ptr++;
}
if (fork() == 0) {
execvp(argv[0], argv);
}
wait(NULL);
}
return 0;
}