程序替换

本篇博客主要讲解 linux 下程序替换函数
邮箱:blbagony@163.com
参考资料:UNIX 环境高级编程
感谢观看,请多多指教

exec 函数
  • 一般我们在一个进程中调用 fork 创建出子进程,该子进程往往需要执行另一个程序,此时我们就需要调用 exec 函数。当进程调用一种 exec 函数时,该进程的执行程序完全替换了新进程,而新程序则从其 main 函数开始执行。注意:exec 并不创建新进程,所以前后子进程的 ID 并没有改变。exec 只是用一个新的程序替换了当前进程的正文、数据、堆和栈段。

  • linux 下提供了六种不同的 exec 函数:
    exec|center
    6 个函数成功不返回,失败返回 -1

  • 函数替换成功后就去执行新的程序,即 path 指定的程序,并且不再返回。当可执行文件不存在,或者没有权限执行会错误返回,返回值为 -1。

参数解析:不带字母 p(表示 path)的 exec 函数,第一个参数必须是程序的绝对路径或相对路径
绝对路径:计算机中的绝对路径是你的主页上的文件在硬盘上的真正的路径(URL和物理路径)

相对路径:相对与某个基准的目录的路径.

例如 "/bin/ls" 就是绝对路径"./a.out" 就是相对路径
对于带字母 p 的函数:如果参数中包含了/,则将其视为路径名。否则视为不带路径的程序名 ,在 PATH 环境环境变量的目录表中搜索这个程序。

带有字母 l(表示list)的 exec 函数要求新程序的每个命令行参数都当作一个独立的参数出递给他,命令行参数的个数可变,所以函数原型中有......中的最后一个参数必须为NULL,然后将该数组地址作为这三个函数的参数。

exec_diff

函数调用
exec_2

注意 execve是系统调用,而其他五个函数都调用 execve

这里写图片描述

实现简易 shell

思路:
1. 父进程通过不断从标准输入读取命令行参数。
2. 将命令行参数解保存到指针数组中。
3. fork 一个子进程,让子进程通过调用 execvp 程序替换。执行用户输入命令。
4. 父进程等待子进程退出,继续读取标准输出。

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <assert.h>
#include <string.h>
#include <sys/wait.h>

const size_t BUFF_SIZE = 256;

void parse(char* str, char* argv[])
{
    assert(str);
    char *token = strtok(str, " ");
    int i = 0;
    argv[i++] = token;
    while (token != NULL) {
        if ( 0 == strncasecmp(token, "quit", 4) ) {
            exit(0); 
        }
        token = strtok(NULL, " ");
        argv[i++] = token;
    }
}

void Exec(char* const argv[])
{
    pid_t id = fork();
    if (id == 0) {
        execvp(argv[0], argv);
        perror("execvp");
    } else if (id > 0) {
        wait(NULL);
    } else {
        perror("fork");
    }
}

void run(){
    char *outbuf[BUFF_SIZE];
    char inbuf[BUFF_SIZE];
    while (1) {
        printf("[blb]# ");
        fflush(stdout);
        bzero(inbuf, sizeof (inbuf));
        bzero(outbuf, sizeof (outbuf));

        /* 1. 从输入流读取字符串 */
        size_t ret = read(0, inbuf, sizeof (inbuf));
        inbuf[ret - 1] = 0;//注意需要把 '\n' 去掉

        /* 2. 解析字符串 */
        parse(inbuf, outbuf);
        /* 3. 执行程序替换 */
        Exec(outbuf);
    }
}

int main()
{
    run();
    return 0;
}

简易的 bash 不能实现内建指令,不支持 > | 等运算符,后面改进时可以在 prase 函数中遇到内建指令就需要父进程自己去亲自执行
什么是内建指令

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值