exec函数、shell的实现

exec函数

问题:为什么bash创建的子进程和自己的不一样?

execl、execlp、execle/

功能:

替换(replace)当前的进程印象(process image)

重点在于replace:可以这么理解,由于身体的细胞一直在衰老更替,七年之后,你身体的细胞都不是原来的细胞了,"替换"成新的细胞了;

execl会替换缓冲区,因此前面需要刷新流;

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

int main()
{
    puts("Begin...");
    fflush(NULL);     在execl前需要刷新流
    
    execl("/bin/date", "date", "+%s", NULL);
    perror("execl()");
    exit(1);

    puts("End...");

    exit(0);
}

shell命令行的工作过程:few三部曲

  • fork()、exec()、wait()进程的三个重要函数
  • 血脉喷张:这就是shell命令行的工作过程:

1、shell主程序fork子进程shell

2、excel将shell替换位命令行(如date)的二进制程序;

3、子程序date干活;

4、shell父程序wait给子程序收尸;

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

int main(int argc, char **argv)
{
    //1、父进程fork();
    printf("Beginning\n");

    fflush(NULL);
    pid_t pid = fork();
    if (pid < 0)
    {
        perror("fork");
        exit(1);
    }
    else if (pid == 0)//2、子进程干活
    {
        execl("/bin/date","date",NULL);//3、子进程整体替换;
        perror("execl");
        exit(1);
    }
    //1、父进程收尸;
    wait(NULL);
    printf("End\n");

    exit(0);
}

父子进程为什么会打印在一个终端:因为父子进程的文件描述符相同指向同一个终端

  • 黑客病毒手段1:通过execl(argv0)将病毒进程隐藏成常规进程名;

shell程序的 简单实现:

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

#define DELIMS " \t\n"

struct cmd_st
{
    glob_t globres;
};


static void prompt(void)
{
    printf("mysh-0.1$ ");
}

static void parse(char *line, struct cmd_st *res)
{
    char *tok;
    int i = 0;

    while(1)
    {
        tok = strsep(&line, DELIMS);
        if(tok == NULL)
            break;
        
        if(tok[0] == '\0')
            continue;

        glob(tok, GLOB_NOCHECK | GLOB_APPEND * i, NULL, &res->globres);
        i = 1;
    }
}

int main()
{
    char *linebuf = NULL;
    size_t linebuf_size = 0;
    struct cmd_st cmd;
    
    while(1)
    {
        pid_t pid;
        prompt();

        if(getline(&linebuf, &linebuf_size, stdin) < 0)
            break;

        parse(linebuf, &cmd);

        if(0)
        {
            // 执行内部命令
            printf("Internal command is not executed\n");
        }
        else
        {
            // 执行外部命令
            pid = fork();

            if( pid < 0)
            {
                perror("fork()");
                exit(1);
            }
            if(pid == 0)
            {
                execvp(cmd.globres.gl_pathv[0], cmd.globres.gl_pathv);
                perror("execvp()");
                exit(1);
            }
            else
            {
                wait(NULL);
            }
        }
    }
    exit(0);
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值