vfork导致父进程环境变量被修改

vfork导致父进程环境变量被修改

vfork版本

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

static int childProcess(void *arg) {
    char* env = getenv("MY_ENV");
    printf("childProcess %d env:%s\n", getpid(), env);
    setenv("MY_ENV", "helloword", 1); 
    exit(0);
}
int main(void) {

    volatile pid_t resultPid = vfork();
    if (resultPid == 0) {
        childProcess(NULL);
    }   
    volatile pid_t resultPid1 = vfork();
    if (resultPid1 == 0) {
        childProcess(NULL);
    }   
    char* env = getenv("MY_ENV");
    printf("main process %d env:%s\n", getpid(), env);
    assert(resultPid != 0); /* childProcess never returns */
    assert(resultPid1 != 0); /* childProcess never returns */
    return 0;
}

运行结果

childProcess 12451 env:(null)
childProcess 12452 env:helloword
main process 12450 env:helloword

可以看出,父进程没有设置环境变量MY_ENV,但是由于子进程12451 设置了环境变量,导致主进程12450 也被设置了。

fork版本

// vfork.c
static int childProcess(void *arg) {
    char* env = getenv("MY_ENV");
    printf("childProcess %d env:%s\n", getpid(), env);
    setenv("MY_ENV", "helloword", 1);
    exit(0);
}
int main(void) {
    // volatile pid_t resultPid = vfork();
    volatile pid_t resultPid = fork();
    if (resultPid == 0) {
        childProcess(NULL);
    }
    // volatile pid_t resultPid1 = vfork();
    volatile pid_t resultPid1 = fork();
    if (resultPid1 == 0) {
        childProcess(NULL);
    }
    char* env = getenv("MY_ENV");
    printf("main process %d env:%s\n", getpid(), env);
    assert(resultPid != 0); /* childProcess never returns */
    assert(resultPid1 != 0); /* childProcess never returns */
    return 0;
}

运行结果

main process 14304 env:(null)
childProcess 14305 env:(null)
childProcess 14306 env:(null)

可以看出,即使子进程设置了环境变量,但是并没有影响其他子进程。

vfork + execve版本

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

static int childProcess(void *arg) {
    char *argVec[10]; //参数数组
    char *envVec[] = {"环境参数1","环境参数2",NULL}; //环境变量数组
    printf("childProcess %d exec\n", getpid());
    execve("./exec", argVec,envVec);
}
static int childProcess1(void *arg) {
    char* env = getenv("MY_ENV");
    printf("childProcess %d env:%s\n", getpid(), env);
    // setenv("MY_ENV", "helloword", 1);
    exit(0);
}
int main(void) {
    volatile pid_t resultPid = vfork();
    // volatile pid_t resultPid = fork();
    if (resultPid == 0) {
        childProcess(NULL);
    }   
    sleep(1);
    volatile pid_t resultPid1 = vfork();
    // volatile pid_t resultPid1 = fork();
    if (resultPid1 == 0) {
        childProcess1(NULL);
    }   
    char* env = getenv("MY_ENV");
    printf("main process %d env:%s\n", getpid(), env);
    assert(resultPid != 0); /* childProcess never returns */
    assert(resultPid1 != 0); /* childProcess never returns */
    return 0;
}
// exec.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#include <sys/types.h>
#include <unistd.h>

int main() {
    char* env = getenv("MY_ENV");
    printf("childProcess %d env :%s\n", getpid(), env);
    setenv("MY_ENV", "helloword", 1); 
    // char* env1 = getenv("MY_ENV");
    // printf("childProcess %d env1:%s\n", getpid(), env1);
    return 0;
}

运行结果

childProcess 16605 exec
childProcess 16605 env :(null)
childProcess 16606 env:(null)
main process 16604 env:(null)

子进程在执行完execve后,修改环境变量对主进程已经没有影响。

结论:

  • fork创建一个进程时,子进程只是完全复制父进程的资源,子进程的修改并不会影响父进程
  • vfork系统调用不同于fork,用vfork创建的子进程与父进程共享地址空间,也就是说子进程完全运行在父进程的地址空间上,如果这时子进程修改了某个变量,这将影响到父进程。
  • 一个进程一旦调用exec类函数,它本身就“死亡”了,系统把代码段替换成新的程序的代码,废弃原有的数据段和堆栈段,并为新程序分配新的数据段与堆栈段,唯一留下的,就是进程号,exec类函数中有的还允许继承环境变量之类的信息,这个通过exec系列函数中的一部分函数的参数可以得到。
  • vfork会保证子进程先运行
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值