【操作系统】进程程序替换之模拟实现一个简易的Shell

本文介绍了exec函数族的原理与应用,包括不同exec函数的区别及如何使用它们替换进程执行的内容。此外,还详细讲解了如何利用这些函数实现一个简单的Shell程序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、替换原理

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

这里写图片描述


2、替换函数:exec函数族
#include<unistd.h>

//argv[0]:可执行文件的文件名
//char *const envp[],构造环境变量

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[]);

命名理解:

  • l(list):表示参数采用列表
  • v(vector):参数用数组
  • p(path):有p自动搜索环境变量PATH
  • e(env):表示自己维护环境变量
函数名参数格式是否带路径是否使用当前环境变量
execl列表不是
execlp列表
execle列表不是不是,需自己组装环境变量
execv数组不是
execvp数组
execve数组不是不是,需自己组装环境变量

函数解释:

  • 这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回。
  • 如果调用出错,则返回-1。
  • exec函数只有出错的返回值,没有成功的返回值。

exec函数族关系图:

只有execve是真正的系统调用,其他的五个函数最终都通过调用execve来实现自己的功能。

这里写图片描述


3、实现一个简易的shell

首先编写一个shell,需要重复以下过程:

  1. 获取命令行
  2. 解析命令行
  3. 建立一个子进程(fork)
  4. 替换子进程(execvp)
  5. 父进程等待子进程(wait)

实现代码:

#include<stdio.h>
#include<unistd.h>
#include<wait.h>
#include<stdlib.h>
#include<string.h>

char *argv[8];
int argc = 0;

void do_parse(char* buf){
    int i;
    int status = 0;

    for(argc=i=0;buf[i];i++){
        if(!isspace(buf[i]) && status == 0){
            argv[argc++] = buf + i;
            status = 1;
        }else if(isspace(buf[i])){
            status = 0;
            buf[i] = 0;
        }
    }
    argv[argc] = NULL;
}

void do_execute(){
    pid_t pid = fork();

    if(pid > 0){
        //father
        int st;
        while(wait(&st) != pid)
            ;
    }else if(pid == 0){
        //child
        execvp(argv[0],argv);
        perror("execvp");
        exit(EXIT_FAILURE);
    }else{
        perror("fork!");
        exit(EXIT_FAILURE);
    }
}

int main(){
    char buf[1024] = {};
    while(1){
        printf("myshell> ");
        fflush(stdout);//刷新缓冲区
        gets(buf);
        do_parse(buf);//解析命令行
        do_execute();//
    }

    return 0;
}

程序运行结果:

这里写图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值