今天分享linux下实现一个简易的minishell程序:
我使用的xshell6写的程序,不知为什么就是看不惯centos6的黑框框,,,
通常连接xshell6后进入就是如下图所示:
用户可以输入一系列指令然后会将结果显示出来,如上图所示
所以要写一个简易shell需要遵循以下过程:
1.获取命令行
2.解析命令行
3.建立一个子进程(fork)
4.替换子进程(execvp)
5.父进程等待子进程退出(wait)
实现代码如下所示:
写一个Makefile文件(项目的自动化辅助构建工具,可以定义项目的整体的构建编译规则)
我编写的Makefile如下图所示:
vi minishell.c文件,你没创建的话系统会帮你创建一个,进入后写入如下代码
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<unistd.h>
4
5 int main()
6 {
7 while(1){
8 printf("[lgl@localhost]$ ");
9 fflush(stdout); //刷新缓冲区,stdout标准输出,可以显示出来否则一直有个\n,无法进行输出
10 char buf[1024] = {0};//字符数组,存放用户输入
11 //%[^\n]:从缓冲区读取字符串遇到\n停下,%*c:从缓冲区取一个字符,scanf()成功则返回值为1,失败为0
12 if(scanf("%[^\n]%*c",buf) != 1){
13 getchar(); //把\n放到getchar()中
14 continue;
15 }
16
17 char* argv[32]; //指针数组来存储每个有效字符串首地址
18 int argc = 0;
19 char* ptr = buf; //创建一个指针指向buf字符数组
20 while(*ptr!='\0'){ //只要没到输入的字符串末尾就继续往下走
21 if(!isspace(*ptr)){ //isspace函数判断是否空格,是的话就返回真
22 argv[argc++] = ptr; //走到不是空格的地方就存下这个位置
23 //然后把这个字符走完,之后在末尾添上'\0'
24 while(*ptr!='\0' && !isspace(*ptr)){
25 ptr++;
26 }
27 }
28 *ptr = '\0';
29 ptr++; //继续往后走判断
30 }
31 argv[argc] = NULL; //走完整个字符串后就在末尾加上NULL
32 if(strcmp(argv[0],"cd")==0){//判断是否是内建命令,是的话,就直接执行,否则改变路径
33 chdir(argv[1]);
34 continue;
35 }
36 int pid = fork();
37 if(pid<0){ //创建子进程失败,则继续创建,因为用户还要输入指令
38 printf("fork error!");
39 continue;
40 }
41 else if(pid==0){//创建子进程来完成程序替换任务
42 if(execvp(argv[0],argv)<0){//返回值<0则说明有错,否则就直接执行替换的程序
43 perror("");
44 }
45 exit(0);//如果有错那就退出
46 }
47 //等待子进程退出,否则子进程会成为僵尸进程
48 wait(NULL);
49 }
50 return 0;
51 }
然后要运行minishell.c文件时只需先make一下,编译minishell.c文件生成一个可执行程序minishell,如下图所示:
然后./minishell就可以运行了,运行结果如下图所示:
可以执行基本的shell命令,然后还可以查看文件内容如下所示:
小结:
这个程序就是综合了进程创建,进程控制,程序替换这几大块的知识来完成的。
所以一定要先理解清楚进程的概念,这几大块的知识还是相当重要的。