Linux--exec族函数及与fork共用

exec族函数

作用:
我们用fork函数创建新进程后,经常会在新进程中调用exec函数去执行另外一个程序。当进程调用exec函数时,该进程被完全替换为新程序。因为调用exec函数并不创建新进程,所以前后进程的ID并没有改变。
exec函数族:
execl, execlp, execle, execv, execvp, execvpe

#include 
extern char **environ;

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[]);
/*
path:可执行文件的路径名字
file:如果参数file中包含/,则就将其视为路径名,否则就按 PATH环境变量,在它所指定的各目录中搜寻可执行文件。
arg:可执行程序所带的参数,第一个参数为可执行文件名字,没有带路径且arg必须以NULL结束
*/

返回值:
  exec函数族的函数执行成功后不会返回,调用失败时,会设置errno并返回-1,然后从原程序的调用点接着往下执行。

例:
有绝对路径

//文件demo.c
#include 
#include 
#include 

int main(void)
{
    printf("before execl\n");
    if(execl("./bin/echoarg","echoarg","abc",NULL) == -1)
    //文件路径./ ...执行文件echoarg,显示内容abc,空结尾。
    //arg:可执行程序所带的参数,第一个参数为可执行文件名字,没有带路径且arg必须以NULL结束
    {
        printf("execl failed!\n");   
        perror("why");//失败的原因   
    }
    printf("after execl\n");
    return 0;
}
//文件echoarg.c
#include 

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

运行结果:

before execl
argv[0]: echoarg
argv[1]: abc

运行 ls:
通过whereis ls找到 ls的路径,然后调用:if(execl("/bin/ls","ls",NULL,NULL) == -1)

运行 ls -l:
通过whereis ls找到 ls的路径,然后调用:if(execl("/bin/ls","ls","-l",NULL) == -1)

获取系统时间date:
通过whereis date找到 date的路径,然后调用:if(execl("/bin/date","date",NULL,NULL) == -1)

族函数带p的:execlp
(不加绝对路径)exaclp函数带p,所以能通过环境变量PATH查找到可执行文件ps

#include 
#include 
#include 

int main(void)
{
    printf("before execlp\n");
    if(execlp("ps","ps","-l",NULL) == -1)
    //通过环境变量PATH查找到可执行文件ps
    {
        printf("execl failed!\n");
    }   
    printf("after execl\n");
    return 0;
}

环境变量:
查询环境变量:echo $PATH

显示当前路径:pwd
修改环境变量:export PATH=$PATH:pwd显示的路径

族函数带v的:execvp
execv带绝对路径

#include 
#include 
#include 

int main(void)
{
    printf("before execlp\n");
	char *argv[] = {"ps",NULL,NULL};
    if(execvp("ps",argv) == -1)
    {
        printf("execl failed!\n");
    }   
    printf("after execl\n");
    return 0;
}

精彩博文: https://blog.csdn.net/u014530704/article/details/73848573

**

exec配合fork使用

**

实现功能:当父进程检测到输入为一的时候,创建子进程把配置文件的字段修改掉。

//changeData文件
/*
修改配置文件config.txt
>  SPEED = 3
>  LENG = 3 
>  SCORE = 9 
>  LEVEL = 5
>  修改为:
>  SPEED = 3
>  LENG = 100 
>  SCORE = 9 
>  LEVEL = 5
*/
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main(int argc,char **argv)
{
	int fdSrc,fdDes;
	char *readBuf = NULL;
	
	if(argc != 2){
		printf("pararm error\n");
		exit(-1);
	}
	
	fdSrc = open(config.txt,O_RDWR);//打开文件
	int size = lseek(fdSrc,0,SEEK_END);
	lseek(fdSrc,0,SEEK_SET);
	readBuf = (char *)malloc(sizeof(char)*size + 8);
	
	int n_read = read(fdSrc,readBuf,1024);
	
	char *p = strstr(readBuf,"LENG=");
	if(p==NULL){
		printf("not founf\n");
		exit(-1);
	}
	p = p+strlen("LENG=");
	*p = "100";
	
	lseek(fdSrc,0,SEEK_SET);//移动光标
	int n_write =write(fdSrc,readBuf,strlen(readBuf));

	close(fdSrc);
	
	return 0;
}

用exec族函数调用changeData文件

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
	pid_t pid;
	int data = 10;
	
	while(1){
		printf("please input a data:\n");
		scanf("%d",&data);
		if(data == 1){
			int fdSrc;
			pid = fork();
			if(pid > 0){
				wait(NULL);
			}
			if(pid == 0){
				execl("./changeData","changeData","config.txt",NULL);				
			}
		}
		else{
			printf("wait ,do nothing!\n");
		}
	}
	
	return 0;
}

你可能感兴趣的:(Linux,linux,算法,运维)