关键字:子进程,exec,环境变量

使用fork或vfork创建子进程后,子进程通常会调用exec函数来执行另外一个程序。系统调用exec用于执行一个可执行程序以

替代当前进程的执行映像。

注意:exec调用并没有创建新的进程。一个进程一旦调用exec函数,它本身就“死亡”了,系统把代码段替换成新的程序的代码,

废弃原有的数据段和堆栈段,并为新程序分配新的数据段与堆栈段,唯一保留的就是进程ID。也就是说,对系统而言,还是

同一个进程,不过执行的已经是另外一个程序了。

exec函数:

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 execvpe(const char *file, char *const argv[],char *const envp[]);

--------------------------------------------------------------------------------

环境变量:用户的主目录,终端类型,当前目录等,它们定义了用户的工作环境,所以称为环境变量。

可以使用指令env查看系统环境变量。

用户也可以修改这个变量的值,以制定自己的工作环境。

代码中通过系统预定义的全局变量environ显示各个环境变量的值。

事实上main函数的完整形式应该是:

int main(int argc, char* argv[], char** envp);

参数envp就是系统环境变量。

测试代码:

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

extern char** environ;

int main(int argc, char** argv, char** envp)
{
    char** p = environ;
    char** q = envp;
    while(*p != NULL)
    {
        printf("%s\n", *p++);
        printf("%s\n", *q++);
        printf("----------\n");
    }

    
    return 0;
}

 

 

-----------------------------------------------------------------------------------------------

exec函数与环境变量的关系:

无论是哪个exec函数,都是可以将可执行程序的路径、命令行参数和环境变量3个参数传递给可执行程序的main函数。

程序一:p.c

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

int main(int argc, char* argv[], char **envp)
{
	int i = 0;

	printf("after execve, my pid is:%d\n", getpid());

	for(i=0;i<argc;i++)
	{
		printf("argv[%d]=%s\n", i, argv[i]);
	}



	return 0;
}

  

 

程序二:ex.c

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



int main(int argc, char* argv[], char* envp[])
{
    pid_t pid = 0;
    int stat;

    printf("test execve\n");
    
    pid = fork();

    if (pid < 0)
    {
        exit(0);
    }
    else if (pid == 0)
    {
        printf("the child's pid is:%d\n", getpid());
        
        execve("p", argv, envp);
        
        printf("go on run\n");
    }
    
    printf("parent is running\n");
    wait(&stat);
    printf("quit\n");

    
    return 0;
}

 

 

将第一个程序编译:

gcc -o p p.c

编译第二个程序:

gcc -o ex ex.c 

执行ex程序:

 

test execve
parent is running
the child's pid is:26152
after execve, my pid is:26152
argv[0]=./ex
argv[1]=ll
quit

 

从执行结果来看,execve调用的程序,保持了原来的进程ID,父进程ID。

同时,我们还可以看到当调用新的可执行程序后,原有的子进程的映像被替代,不在被执行。

子进程不会去执行printf("go on run\n");因为子进程已经被新的执行映像替代。

 

执行新程序后的进程保持了原来进程的许多特征,如:

1、文件锁

2、控制终端

3、当前工作目录

4、根目录

5、创建文件时使用的屏蔽字

6、进程信号屏蔽字

7、未决警告

8、和进程相关的使用处理器的时间

9、实际用户ID

10、实际组ID

posted on 2017-02-20 17:27  邶风  阅读(1241)  评论(0编辑  收藏  举报