Linux下进程程序替换及简单的shell的实现

替换原理:

用fork创建进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换。从新进程的启动例程开始执行,调用exec函数并不创建新进程,所以调用exec函数前后进程的id并未改变。

替换函数:

有六种以exec开头的函数,统称exec函数:

#include<unistd.h>

int execl(const char*path,const char*arg)

int execlp(const char*file,const char*arg)

int execle(const char*path,const char*arg,...,char const envp[])

int execv(const char*path,char *const argv[])

int execvp(const char*file,char*const argv[])

int execve(const char*path,char* const argv[],char*const envp[])

这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回。

如果调用出错则返回-1。

所以exec函数只有出错的返回值而没有成功的返回值。

这些函数原型看起来很容易混淆,但只要掌握了规律就很好记。

l(list):表示参数采用列表

v(vector):参数用数组

p(path):有p自动搜素环境变量path

e(env):表示自己维护的环境变量

事实上只有execve是真正的系统调用,其他几个函数最终都调用execve函数。

下面使用exec函数来实现一个简单的shell

直接上代码

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值