进程程序替换及shell的实现

一、进程程序替换

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

替换函数

#include<stdio.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)这些函数如果调用成功则加载新的程序从启动代码开始新的执行,不再返回

(2)如果调用出错则返回-1

(3)exec函数只有出错的返回值而没有成功的返回值

函数规律:

·函数名不带p:第一个参数必须是程序的相对路径和绝对路径

·函数名带e:可以把一份新的环境变量传给它,其他exec函数仍使用当前的环境变量表执行新程序

·函数名带l:要求将新程序的每个命令行参数都当做第一个参数传给它,命令行参数的个数是可变的,而且最后一个可变参数应该是NULL

·函数名带v:应该先构造一个指向各参数的指针数组,然后将该数组的首地址当做参数传给它,数组中的最后一个指针也应该是NULL

参照下表:


例:exec函数

1、简单的hello.c文件

1 #include<stdio.h>
  2 int main()
  3 {
  4     printf("hello word!\n");
  5     return 0;
  6 }

2、exec函数

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 
  4 int main()
  5 {   
  6     char *const argv[] = {"ps","ef",NULL};
  7     char *const envp[] = {"PATH=/bin:/usr/bin","TERM=console",NULL};
  8     
  9     execl("/bin/ps","ps","-ef",NULL);
 10     
 11     execlp("ps","ps","-ef",NULL);
 12     
 13     execle("ps","ps","-ef",NULL,envp);
 14     
 15     execv("/bin/ps",argv);
 16     
 17     execvp("ps",argv);
 18     
 19     execve("/bin/ps",argv,envp);
 20     
 21     exit(0);
 22 }

只有execve是真正的系统调用,其他5个函数最终都调用execve


二、根据exec函数做一个简易的shell

1 #include<unistd.h>
  2 #include<sys/wait.h>
  3 #include<stdio.h>
  4 #include<string.h>
  5 #include<stdlib.h>
  6 
  7 char *argv[8];
  8 int argc = 0;
  9 
 10 void do_parse(char *buf)
 11 {
 12     int i;
 13     int status = 0;
 14     for(argc = i = 0;buf[i];i++){
 15         if(!isspace(buf[i]) && status == 0){
 16             argv[argc++] = buf+i;
 17             status = 1;
 18         }
 19         else if(isspace(buf[i])){
 20             status = 0;
 21             buf[i] = 0;
 22         }
 23     }
 24 }
 25 void do_execute()
 26 {
 27     pid_t pid = fork();
 28     switch(pid){
 29         case -1:
 30         perror("fork");
 31         exit(EXIT_FAILURE);
 32         break;
 33         case 0:
 34         execvp(argv[0],argv);
 35         perror("execvp");
 36         exit(EXIT_FAILURE);
 37         default:
 38         {
 39             int set;
 40             while(wait(&set) != pid)
 41                 ;
 42         }
 43     }
 44 }
 45 int main()
 46 {
 47     char buf[1024] = {};
 48     while(1){
 49         printf("myshell>");
 50         scanf("%[^\n]%*c",buf);
 51         do_parse(buf);
 52         do_execute();
 53     }
 54 }



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值