3.4.10.exec族函数及实战2

3.4.10.exec族函数及实战2
3.4.10.1、execlp和execvp
(1)加p和不加p的区别是:不加p时需要全部路径+文件名,如果找不到就报错了。加了p之后会多帮我们到PATH所指定的路径下去找一下。

execlp 在测试这个函数之前,先 测试 :

/* 当不给 execl 命令路径时,返回值 -1, 代表execl 执行错误  */

代码:

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


int main(void)
{
	/* 接收 fork 的返回值 */
	pid_t pid = -1;
	/* 接收 wait waitpid 的返回值 */
	pid_t ret = -1;
	/*  wait waitpid 传参,进程状态信息 */
	int status = -1;
	
	
	/*  fok 返回一个 进程的 pid  */
	pid = fork();  //fork 函数返回 2 次  : 等于0 是子进程, 大于0是父进程
	
	if(0 == pid)
	{
		/* execv 定义字符串数组 传参  */
		char * const arg[] = {"ls",  "-l", "-a", NULL};
		
		/* 这里一定是 子进程 ,   子进程先结束,成为僵尸进程 ,一定要保证子进程先结束 */
		printf("子进程 child pid = %d \n", getpid()); 
		
		/*  在子进程 中执行 ls 命令*/
		//execl("/bin/ls", "ls",  "-l", "-a", NULL); /*  "/bin/ls" :命令的全路径。 "ls": 这个是命令 ! "-l","-a", 第3、4个可以是参数,5个、6个...参数也可以,必须以NULL结尾 */
		//execv("/bin/ls", arg);
		//execl("hello","hello",NULL);  	/* 第一个"hello"是当前目录下的路径和可执行文件名, 第2个"hello"是命令名字,最后以NULL结尾 */
		
		//execlp();  
		
		int ret =  execl( "ls",  "-l", "-a", NULL);/* 当不给 execl 命令路径时,返回值 -1, 代表execl 执行错误  */
		printf("execl 的返回值 ret = %d \n", ret);
		return  99;
	}	
	else if (pid > 0)
	{
		/*  加入 sleep , 让子进程 先运行结束,子进程成为僵尸进程, */
		sleep(1);
		printf(" 父进程中打印 子进程id = %d \n ",pid);                   /* 这里一定是 父进程 */
		/* 这里一定是 父进程 */
		ret = waitpid(pid,&status,0);  /* waitpid ,-1表示不管是那个子进程都回收 ,0 表示 阻塞式 */
		printf("子进程已经被回收,子进程pid = %d \n", ret);
		printf("子进程是否正常退出:%d \n", WIFEXITED(status));  /* WIFEXITED  判断是否正常退出 */
		printf("子进程是否 非正常退出:%d \n", WIFSIGNALED(status));  /* WIFSIGNALED 判断是否 非正常退出 */
		printf("子进程正常终止情况下的  进程返回值:%d \n", WEXITSTATUS(status));  /* WEXITSTATUS 正常终止情况下的  进程返回值 */
	}
	else
	{
		/* 这里一定是 fork出错了  */
		perror("fork");
		return -1;
	}
	

	
	
	return 0;
}

 运行结果:

 

/* 如果当前目录下有 ls 命令, execl 不传命令路径  也可以执行  */

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


int main(void)
{
	/* 接收 fork 的返回值 */
	pid_t pid = -1;
	/* 接收 wait waitpid 的返回值 */
	pid_t ret = -1;
	/*  wait waitpid 传参,进程状态信息 */
	int status = -1;
	
	
	/*  fok 返回一个 进程的 pid  */
	pid = fork();  //fork 函数返回 2 次  : 等于0 是子进程, 大于0是父进程
	
	if(0 == pid)
	{
		/* execv 定义字符串数组 传参  */
		char * const arg[] = {"ls",  "-l", "-a", NULL};
		
		/* 这里一定是 子进程 ,   子进程先结束,成为僵尸进程 ,一定要保证子进程先结束 */
		printf("子进程 child pid = %d \n", getpid()); 
		
		/*  在子进程 中执行 ls 命令*/
		//execl("/bin/ls", "ls",  "-l", "-a", NULL); /*  "/bin/ls" :命令的全路径。 "ls": 这个是命令 ! "-l","-a", 第3、4个可以是参数,5个、6个...参数也可以,必须以NULL结尾 */
		//execv("/bin/ls", arg);
		//execl("hello","hello",NULL);  	/* 第一个"hello"是当前目录下的路径和可执行文件名, 第2个"hello"是命令名字,最后以NULL结尾 */
	
		//execlp( "ls","-l","-a", NULL);/* 加p 后,就会去 PATH 路径去找ls命令  */
	
		execl( "ls",  "-l", "-a", NULL);  /* 如果当前目录下有 ls 命令, execl不传命令路径也可以执行  */
	
		return  99;
	}	
	else if (pid > 0)
	{
		/* 这里一定是 父进程 */
		printf(" 父进程中打印 子进程id = %d \n ",pid);                   /* 这里一定是 父进程 */
	}
	else
	{
		/* 这里一定是 fork出错了  */
		perror("fork");
		return -1;
	}
	

	
	
	return 0;
}

运行结果:

 

开始测试 execlp                               

 

代码:

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


int main(void)
{
	/* 接收 fork 的返回值 */
	pid_t pid = -1;
	/* 接收 wait waitpid 的返回值 */
	pid_t ret = -1;
	/*  wait waitpid 传参,进程状态信息 */
	int status = -1;
	
	
	/*  fok 返回一个 进程的 pid  */
	pid = fork();  //fork 函数返回 2 次  : 等于0 是子进程, 大于0是父进程
	
	if(0 == pid)
	{
		/* execv 定义字符串数组 传参  */
		char * const arg[] = {"ls",  "-l", "-a", NULL};
		
		/* 这里一定是 子进程 ,   子进程先结束,成为僵尸进程 ,一定要保证子进程先结束 */
		printf("子进程 child pid = %d \n", getpid()); 
		
		/*  在子进程 中执行 ls 命令*/
		//execl("/bin/ls", "ls",  "-l", "-a", NULL); /*  "/bin/ls" :命令的全路径。 "ls": 这个是命令 ! "-l","-a", 第3、4个可以是参数,5个、6个...参数也可以,必须以NULL结尾 */
		//execv("/bin/ls", arg);
		//execl("hello","hello",NULL);  	/* 第一个"hello"是当前目录下的路径和可执行文件名, 第2个"hello"是命令名字,最后以NULL结尾 */
		//execl( "ls",  "-l", "-a", NULL);  /* 如果当前目录下有 ls 命令, execl 也可以执行  */
		execlp( "ls","ls","-l","-a", NULL);/* 加p 后,就会去 PATH 路径去找ls命令  */
	
		return  99;
	}	
	else if (pid > 0)
	{
		/* 这里一定是 父进程 */
		printf(" 父进程中打印 子进程id = %d \n ",pid);                   /* 这里一定是 父进程 */
	}
	else
	{
		/* 这里一定是 fork出错了  */
		perror("fork");
		return -1;
	}
	

	
	
	return 0;
}

执行结果:

 

3.4.10.2、execle和execvpe
(1)main函数的原型其实不止是int main(int argc, char **argv),而可以是
int main(int argc, char **argv, char **env)    第三个参数是一个字符串数组,内容是环境变量。

代码 :

hello2.c

#include <stdio.h>


                                  /* env 就是我们给main 函数额外传递的 环境变量 字符串数组 */
int main(int argc, char **argv, char **env)
{
	int i = 0;
	  /* 打印 argc 的参数 */
	printf("argc = %d  \n",argc);
      /* 打印 argv 的参数 */	
	while(NULL != argv[i])
	{
		printf("argv[%d] = %s \n", i, argv[i]);
		i++;
	}
	
	i = 0;
	    /* 打印 env 的参数 */	
	while(NULL != env[i])
	{
		printf("env[%d] = %s \n", i, env[i]);
		i++;
	}
	

	return 0;
}


运行结果:


(2)如果用户在执行这个程序时没有传递第三个参数,则程序会自动从父进程继承一份环境变量(默认的,最早来源于OS中的环境变量, 例如上面的 ./hello);

如果我们exec的时候使用execlp或者execvpe去给传一个envp数组,则程序中的实际环境变量是我们传递的这一份(取代了默认的从父进程继承来的那一份)

代码:  如果我们exec的时候使用execlp或者execvpe去给传一个envp数组

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


int main(void)
{
	/* 接收 fork 的返回值 */
	pid_t pid = -1;
	/* 接收 wait waitpid 的返回值 */
	pid_t ret = -1;
	/*  wait waitpid 传参,进程状态信息 */
	int status = -1;
	
	
	/*  fok 返回一个 进程的 pid  */
	pid = fork();  //fork 函数返回 2 次  : 等于0 是子进程, 大于0是父进程
	
	if(0 == pid)
	{
		
		
		/* 这里一定是 子进程 ,   子进程先结束,成为僵尸进程 ,一定要保证子进程先结束 */
		printf("子进程 child pid = %d \n", getpid()); 
		
			/* envp  定义字符串数组 传参  */
		char * const envp[] = {"AA=123",  "bb=c1d2",  NULL};
		execle("hello", "hello", NULL, envp);/* 如果我们exec的时候使用execlp或者execvpe去给传一个 envp数组, */
		return  99;
	}	
	else if (pid > 0)
	{
		/* 这里一定是 父进程 */
		printf(" 父进程中打印 子进程id = %d \n ",pid);                   /* 这里一定是 父进程 */
	}
	else
	{
		/* 这里一定是 fork出错了  */
		perror("fork");
		return -1;
	}
	

	
	
	return 0;
}

 

运行结果:

 

 代码来自:朱老师物联网大讲堂

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大漠飞鹰6666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值