shell:程序员和操作系统之间沟通的桥梁,媒婆。
敲下的指令都是在 shell 中执行的,Linux 系统中默认的那个 shell 叫做 bash。
shell 基本运行原理
首先当我把 shell 启动(就是打开一个窗口)起来的时候,它就在等待用户进行输入,当用户输入指令后,shell 需要对用户输入的指令串进行解析,弄清楚这条指令到底要干什么,指令名也就是对应的可执行程序文件名是什么,以及一些相关的运行参数是什么,接下来 shell 会创建出一个子进程,子进程进行程序替换去执行 ls(以 ls 为例) 相关代码,而父进程也就是 shell 进程会进行进程等待,等到子进程把 ls 相关代码执行完了,wait 一回收,就可以继续让用户输入下一条指令了。
注意
不能把当前的 shell 进程替换成 ls,因为 shell 不可能只执行一条指令就结束了。
实现流程
1、等待用户输入指令
2、解析用户输入的指令,解析是为了搞清楚用户想要执行的可执行程序是什么,以及对应的参数是什么
3、myshell 进程创建子进程
a)子进程进行程序替换,替换成刚才输入的指令对应的可执行文件
b)父进程进行进程等待,等待子进程运行结束
c)myshell 进程继续从 1 开始循环整个流程
实现代码
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *argv[8] = {NULL};
int argc = 0;
int do_parse(char *buf)
{
int i, r, status = 0, ret;
for (argc=i=0; buf[i]; i++)
{
r = isspace(buf[i]);
if (!r && !status)
{
argv[argc++] = buf + i;
status = 1;
}
else if (r)
{
status = 0;
buf[i] = '\0';
}
}
if (argc >= 8)
{
printf("parameter number(%d) too much\n", argc);
ret = -1;
}
else
{
argv[argc] = NULL;
ret = 0;
}
return ret;
}
void do_exec()
{
pid_t pid = fork();
switch (pid)
{
case -1:
perror("fork");
exit(EXIT_FAILURE);
case 0:
execvp(argv[0], argv);
perror("execvp");
exit(EXIT_FAILURE);
default:
{
int status;
while (wait(&status) != pid);
if (status & 0xff)
printf("child process signal id: %d\n"
, status & 0x7f);
else
printf("child process status code: %d\n"
, (status >> 8) & 0xff);
}
}
}
/* myshell */
int main()
{
char buf[1024] = {};
while (1)
{
printf("\nmyshell> ");
scanf("%[^\n]%*c", buf);
if (do_parse(buf) < 0)
continue;
do_exec();
}
return 0;
}
/* myshell_ut */
int main()
{
printf("test myshell ut, sleep 60s\n");
sleep(60);
return 0;
}