初学-Linux多进程--exec族函数

前言

在我们需要使用多进程编程时,有两种比较常见的情况

  1. 一个父进程希望复制自己,使父、子进程同时执行不同的代码段。在网络服务进程中是常见的——父进程等待客户端得到服务请求。当这种请求到达时,父进程调用fork函数,使子进程处理此请求。父进程继续等待下一个服务请求到达、
  2. 一个进程哦要执行一个不同的程序。这对shell是常见的情况。在这种情况下,子进程fork返回后立即调用exec

exec族函数的介绍:

在调用进程内部执行一个可执行文件。可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。

函数族:

exec函数族分别是:execl, execlp, execle, execv, execvp, execvpe

函数原型:

我们可在Linux的终端中输入man exec 查看到函数信息如下:

#include <unistd.h>

extern char **environ;

int execl(const char *pathname, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *pathname, const char *arg, ...);
int execv(const char *pathname, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);

返回值

man手册中是这么说的,翻译之后的大概意思为:Exec()函数仅在发生错误时返回。返回值为-1,并设置errno以指示错误。


常用函数介绍

exec族函数,在函数名中结尾的字母大有玄机:

l:使用参数列表
p:使用文件名,从PATH环境中进行寻找可执行文件
v:要先构造一个指向各参数的指针数组,然后将该数组的地址作为这些函数的参数
e:多了envp[]数组,使用新的环境变量代替调用进程的环境变量。

由于exec函数极难分辨和记忆,对于新手而言,我们就学会使用其中的几个就可以满足我们的需求了。


execl函数

函数原型如下:int execl(const char *pathname, const char *arg, ...);。其中参数pathname表示可执行文件的路径,arg是参数。在没有其他参数,末尾要写上NULL作为参数。

那接下来我们简单的使用一下这个函数吧。

首先我们先编写一个简单的c语言代码生成可执行文件用于测试execl函数的功能。

#include <stdio.h>

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

这段代码的作用是便利输出可执行文件的参数。我们使用 gcc xxx.c -o test编译成我们想好的用户名。

接下来我们编写execl的代码。

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

int main()
{
	printf("before execl\n");
	if(execl("./test","text1","text2",NULL) == -1)
	{
		printf("execl error\n");
		perror("why");
	}
	printf("after execl\n");
	return 0;
}

我们可以通过perror输出错误信息。当出现错误时,会输出错误信息。

运行失败则结果如下:

before execl
execl error
why: Permission denied
after execl

如果运行成功,则可以看到结果:

before execl
argv[0] = text1
argv[1] = text2

通过上述代码效果,我们可以简单的知道如何使用execl函数,并且我们发现,当出现错误时,函数会继续回到出现错误的地方继续往下执行代码。

execl小练习

接下来我们做一个小练习

需求

使用execl函数实现以下获取现在的时间:

在Linux中,有一个命令date可以获取到系统现在的时间。我们先使用whereis date获取到date命令的位置。

hyx@hyx-virtual-machine:~/c_project/c_Process$ whereis date
date: /usr/bin/date /usr/share/man/man1/date.1.gz

/usr/bin目录下。接下来,我们使用execl实现一下:

int main()
{
	printf("show now date:\n");
	if(execl("/usr/bin/date","date",NULL) == -1)
	{
		printf("execl error\n");
		perror("why");
	}
	printf("after execl\n");
	return 0;
}

运行结果如下:

show now date:
2024年 03月 29日 星期五 00:00:54 CST

execlp函数

在我们学会execl函数之后,我们会有这种感受,就是当我们要调用这些Linux的命令时,我们每次都需要先whereis xxx来获取到命令所在的位置。才能调用,让我们觉得比较麻烦。

那使用execlp函数的优势就来了。我们修改一下上面的代码。

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

int main()
{
	printf("show now date:\n");
	if(execlp("date","date",NULL) == -1)
	{
		printf("execl error\n");
		perror("why");
	}
	printf("after execl\n");
	return 0;
}

我们将execl替换成execlp,execlp他能自动从环境变量中获取到位置,然后在其中进行寻找。那如果我们想要用execlp函数之间方便的执行我们自己生成的可执行文件。我们就只需要将我们写的文件位置加入到环境变量中就可以实现了。

在Linux系统中,我们可以使用export &PATH:/xxxx/xxx就可以添加我们的文件位置到环境变量中。快去试试吧。


execvp函数

execvp函数与execlp函数区别就是将这些参数放在一个数组中,然后在函数中将这个数组代替那些参数就好了。

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

int main()
{
	char* arrgv[] = {"date",NULL};
	printf("show now date:\n");
	if(execvp("date",arrgv) == -1)
	{
		printf("execl error\n");
		perror("why");
	}
	printf("after execl\n");
	return 0;
}

至于execv函数则是类似的。就不过多赘述了。

总结

至此,execc族函数就差不多介绍完了,通过exec族函数,我们可以将复杂的任务拆分成多个小的、独立的程序,每个程序负责完成一个特定的任务。这样,我们可以更容易地编写、测试和维护代码,同时也可以避免代码重复。

  • 11
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

坏柠

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

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

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

打赏作者

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

抵扣说明:

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

余额充值