进程程序替换

1什么是进程替换

#include<stdio.h>    
#include<unistd.h>    
    
int main()    
{    
    printf("test.c...begin\n");    
    execl("/usr/bin/ls","ls","-l","-a",NULL);                                                                                                    
    printf("test.c...end\n");    
  return 0;    
}    

可以看到,进程在运行到一半,最后一句的printf没有执行,这是为什么呢?

因为程序被替换了

exec*系列的函数,可以替换当前的程序,进程的程序替换,本质上还是那一个进程,进程不变,但是进程里的程序变了,

要是把代码改成多进程版本,让子进程替换,那么父子共享的代码和数据,都要进行写时拷贝

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

对于int execl(const char *path, const char *arg, ...);

参数的含义,第一个参数path:表示怎么找到函数,所以要传函数的路径,第二个参数arg:表示怎么用函数,怎么用,所以要传命令行指令,比如:

execl("/usr/bin/ls", "ls","-l","-a",NULL)

如果是多个命令,就用逗号分开,结尾要用NULL

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

第二个参数变成argv指针数组,我们可以自己写一个数组,把命令行指令写进数组里,直接传数组就可以

··

char *const argv[] = 

  {
  (char*)"ls",
  (char*)"-l",
  (char*)"-a",
  (char*)"--color",
  NULL};

因为argv的类型是char*,"ls"是const char*,所以给"ls"加个(char*)会比较好,注意,结尾依然是NULL,

所以我们传参时可以

execv("/usr/bin/ls", argv);

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

我们可以把第一个参数变成文件名字,然后execvp就可以根据文件名字查找这个文件

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

第三个参数是环境变量

替换环境变量

  • 替换全新的环境变量
  • 用父进程的环境变量environ
  • 也可以修改父进程的环境变量,然后替换给子进程

比如:

#include <iostream>
#include <unistd.h>
using namespace std;


int main(int argc, char *argv[], char *env[])
{
    int i = 0;
    for(; argv[i]; i++)
    {
        printf("argv[%d] : %s\n", i, argv[i]);
    }

    printf("-------------------------------\n");
    for(i=0; env[i]; i++)
    {
        printf("env[%d] : %s\n", i, env[i]);
    }
    printf("-------------------------------\n");

    cout << "hello C++, I am a C++ pragma!: " << getpid() << endl;
    cout << "hello C++, I am a C++ pragma!: " << getpid() << endl;
    cout << "hello C++, I am a C++ pragma!: " << getpid() << endl;
    cout << "hello C++, I am a C++ pragma!: " << getpid() << endl;

    return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

int main()
{
    printf("testexec ... begin!\n");
    pid_t id = fork();
    if(id == 0)
    {
        putenv("HHHH=111111111111111111");//修改父进程的环境变量
        // 我的父进程本身就有一批环境变量!!!, 从bash来
        char *const argv[] = //命令行参数
        {
            (char*)"mypragma",
            (char*)"-a",
            (char*)"-b",

            NULL
        };
        //char *const envp[] =
        //{
        //    (char*)"HAHA=111111",
        //    (char*)"HEHE=222222",
        //    NULL
        //};
        extern char**environ;
        printf("child pid: %d\n", getpid());
        sleep(2);
        execvpe("./mypragma", argv, environ);
        
        //execvpe("./mypragma", argv, envp);
        //execl("/usr/bin/python3", "python3", "test.py", NULL);
        //execl("/usr/bin/bash", "bash", "test.sh", NULL);
        //execl("./mypragma", "mypragma", NULL);
        //sleep(2);
        //char *const argv[] = 
        //{
        //    (char*)"ls",
        //    (char*)"-l",
        //    (char*)"-a",
        //    (char*)"--color",
        //    NULL
        //};
        child
        //execl("/usr/bin/top", "top", NULL);
        //execlp("top", "top", NULL);
        //execv("/usr/bin/ls", argv);
        //execvp("ls", argv);
        exit(1);
    }

    // fahter
    int status = 0;
    pid_t rid = waitpid(id, &status, 0);
    if(rid > 0)
    {
        printf("father wait success, child exit code: %d\n", WEXITSTATUS(status));
    }
    printf("testexec ... end!\n");
    return 0;
}

可以看出,我们可以修改父进程的环境变量,然后替换给子进程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值