在进程的创建上Unix采用了一个独特的方法,它将进程创建与加载一个新进程映象分离。这样的好处是有更多的余地对两种操作进行管理。
当我们创建了一个进程之后,通常将子进程替换成新的进程映象,这可以用exec系列的函数来进行。当然,exec系列的函数也可以将当前进程替换掉。
?
头文件<unistd.h>
功能用exec函数可以把当前进程替换为一个新进程。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[]);
参数
* path参数表示你要启动程序的名称包括路径名
* arg参数表示启动程序所带的参数
* 带'l'的表示可变参数列表(argument list(仅仅自己理解方便记忆))
* 带'v'的表示参数是(char* argv[](仅仅自己理解方便记忆))
* 带‘p'的表示 会从环境变量中搜索是否有这个程序存在
* 带’e'的表示 会传一个环境信息
返回值:
* 成功 0
* 失败 -1
?
代码段、数据段被替换,之后的代码不会被执行
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define ERR_EXIT(m) do { perror(m); exit(EXIT_FAILURE); } while (0)
int main(int argc, char *argv[])
{
printf("Entering main ...\n");
execlp("ls","ls","-hl",NULL);
printf("Exiting main ...\n");
return 0;
}
?
替换进程并不会修改原进程的id
#include <stdio.h>
#include <unistd.h>
int main(void)
{
printf("pid : %d\n",getpid());
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define ERR_EXIT(m) do { perror(m); exit(EXIT_FAILURE); } while (0)
int main(int argc, char *argv[])
{
printf("Entering main ...\n");
printf("before replace pid : %d\n",getpid());
//代码段、数据段被替换
//int ret = execlp("./hello","hello",NULL);
//linux默认情况下是在环境变量(echo $PATH)下搜索源程序
int ret = execlp("hello","hello",NULL);
if(ret == -1)
perror("execlp error");
printf("Exiting main ...\n");
return 0;
}
?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define ERR_EXIT(m) do { perror(m); exit(EXIT_FAILURE); } while (0)
int main(int argc, char *argv[])
{
char* const args[] = {"ls","-l",NULL};
printf("Entering main ...\n");
"第一个参数可以是绝对路径,也可以是相对路径,也可以不带路径"
//int ret = execlp("ls","ls","-l",NULL);
int ret = execvp("ls",args);
if(ret == -1)
perror("execlp error");
printf("Exiting main ...\n");
return 0;
}
?
例子1
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define ERR_EXIT(m) do { perror(m); exit(EXIT_FAILURE); } while (0)
int main(int argc, char *argv[])
{
printf("Entering main ...\n");
//带'p'的表示会从环境变量或指定的路径获取文件
//execlp("ls","ls","-hl",NULL);
char *const args[] = {"ls", "-hl", NULL};
//execvp("ls", args);
// 并不会在环境变量中搜索,这个地方必须给出一个路径(相对路径和绝对路径都可以)
//int ret = execv("ls", args);
//int ret = execl("ls","ls","-hl",NULL);
if( ret < 0 )
{
perror("execl");
}
printf("Exiting main ...\n");
return 0;
}
?
例子2
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define ERR_EXIT(m) do { perror(m); exit(EXIT_FAILURE); } while (0)
int main(int argc, char *argv[])
{
printf("Entering main ...\n");
//execl执行hello,会将当前的环境信息传递给hello,
//而当前进程的环境信息,是从shell中继承下来的
//简单的说,就是执行“execl”这个程序的的时候,shell会被做为参数,传递到进程中,
//在进程中又调用execl,执行"hello"这个程序,“execl”又将shell作为参数传递到“hello"这个进程中
/* int ret = execl("./hello", "hello", NULL);
if(ret == -1)
{
perror("execl");
} */
//设置自己的环境变量信息
char* const envp[] = {"AA=1", "BB=2", NULL};
int ret = execle("./hello", "hello", NULL, envp);
if(ret == -1)
{
perror("execl");
}
printf("Exiting main ...\n");
return 0;
}
?
例子3
#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
//全部变量,C库中已存在,此处声明下就可以
extern char** environ;
int main(int argc, char const *argv[])
{
printf("hello! pid = %d\n",getpid());
int i;
for(i=0; environ[i] != NULL; ++i)
{
printf("%s\n",environ[i]);
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#define ERR_EXIT(m) do { perror(m); exit(EXIT_FAILURE); } while (0)
int main(int argc, char *argv[])
{
printf("Entering main ...\n");
/*
man 2 fcntl;
File descriptor flags
The following commands manipulate the flags associated with a file descriptor. Currently, only one such flag
is defined: FD_CLOEXEC, the close-on-exec flag. If the FD_CLOEXEC bit is 0, the file descriptor will remain
open across an execve(2), otherwise it will be closed.
*/
//如果将一个文件描述符设置为FD_CLOEXEC,当我们调用execve进行替换的时候,文件描述符会被关闭
int ret = fcntl(1, F_SETFD, FD_CLOEXEC);//置1
if(ret == -1)
{
perror("fcntl");
}
//execlp替换成功,但是因为设置了FD_CLOEXEC,调用hello的时候,1号文件描述符被关闭了,所以”hello"程序无法输出
//对于open()函数,在打开文件的时候,我们可以加O_CLOEXEC,表示将FD_CLOEXEC置为1,当调用exec系列会自动关闭文件描述符
ret = execlp("./hello", "hello", NULL);
if(ret == -1)
{
perror("execl");
}
printf("Exiting main ...\n");
return 0;
}
原文:https://www.cnblogs.com/s3320/p/11397380.html