1 /*写一个属于自己的微型myshell
2 * 功能:myshell>ls
3 * 能够执行基础Linux 命令
4 *
5 */
6 #include<stdio.h>
7 #include<unistd.h>
8 #include<errno.h>
9 #include<string.h>
10 #include<stdlib.h>
11 //1、获取终端输入
12 //2、解析输入(按空格解析到一个一个的命令参数)
13 //3、创建一个子进程
14 // 在子进程中进行程序替换,让子进程运行命令
15 //4、等待子进程运行完毕,收尸,获取状态退出码
16 int argc;
17 char *argv[32];
18 int param_parse(char *buff){
19 if(buff==NULL)
20 return -1;
21 char *ptr=buff;
22 char *tmp=ptr;
23 argc=0;
24 while((*ptr)!='\0')
25 {
26 //当遇到空格,并且下一个位置不是空格的时候将空格位置置为'\0'
27 //不过我们将使用argv[argc]来保存这个字符串的位置
28 if(*ptr==' '&&*(ptr+1)!=' ')
29 {
30 *ptr='\0';
31 argv[argc]=tmp;
32 tmp=ptr+1;
33 argc++;
34 }
35 ptr++;
36 }
37 argv[argc++]=tmp;
38 argv[argc]=NULL;
39 }
40
41 int exec_cmd()
42 {
43 int pid=0;
44
45 pid=fork();
46 if(pid<0)
47 {
48 return -1;
49 }else if(pid==0)
50 {
51 execvp(argv[0],argv);
52 exit(0);
53 }
54 //父进程在这里必须等待子进程退出,来看看子进程为什么会退出了
55 //是不是出现了什么错误,通过获取状态码,并且转换以下退出码所对应的错误信息进行打印
56 int statu;
57 wait(&statu);
58 //判断子进程是否是代码运行完毕退出
59 if(WIFEXITED(statu)){
60 //获取子进程错误退出码,并将转换打印出文本信息
61 printf("%s\n",strerror(WEXITSTATUS(statu)));
62 }
63 }
64
65 int main()
66 {
67 while(1){
68 printf("myshell>");
69 char buff[1024]={0};
70 //%[^\n] 获取数据直到遇到\n为止
71 //%*c 清空缓存区,数据不要了。
72 scanf("%[^\n]%*c",buff);
73 printf("%s\n",buff);
74 param_parse(buff);
75 exec_cmd();
76 }
77
78 return 0;
79
80
来看看运行结果
之前在[long@localhost]进程下执行命令,当实现了自己的shell后,在myshell进程下执行命令,此时Linux默认的进程将成为bash后台子程序
./MYSHELL 的父进程ppid为2543,此时2543对应的进程是bash,所以之前的shell被转化为后台进程,MYSHELL成为了当前运行的进程。
当前运行的程序为前台进程,前台进程只能有一个,而后台进程可以有多个,当结束了前台进程,后台进程会有一个进程来作为前台进程。