首页 > 其他分享 >unix中的exec族函数介绍

unix中的exec族函数介绍

时间:2024-09-29 18:47:44浏览次数:9  
标签:函数 exec int pid char unix printf test NULL

一、前言

本文将介绍unix中exec族函数,包括其作用以及使用方法。当一个进程调用fork函数创建一个新进程后,新进程可以直接执行原本正文段的其他内容,但更多时候,我们在一个进程中调用fork创建新的进程后,希望新进程能够执行其他的程序。(举个实际的例子,A进程调用fork后,我们更多的时候是希望子进程能够运行B程序,而不是用于处理A进程特定的内容)exec族函数的作用就是让一个进程执行另一个程序。
本文将围绕如下内容展开:
1.exec族函数的原理
2.exec族各函数介绍

二、exec族函数原理

当一个进程调用了exec类函数后,该进程的正文段、数据段、堆、栈都替换为磁盘中其他指定的程序的内容,即子进程的进程空间被替换了其他内容。不过子进程的PID是不变的。子进程从新程序的main函数开始执行。新程序会继承子进程的如下信息:

  1. 文件描述符:新程序会继承调用进程的打开文件描述符,包括标准输入、标准输出和标准错误,除非这些文件描述符在调用 exec 前被显式地关闭或更改。
  2. 环境变量:新程序会继承调用进程的环境变量。
  3. 当前工作目录:新程序会继承调用进程的当前工作目录。
  4. 进程用户和组 ID:新程序会继承调用进程的用户 ID(UID)和组 ID(GID)。
  5. 信号处理状态:新程序会继承调用进程的信号处理状态,包括信号屏蔽字。
  6. 一些状态信息:比如进程优先级(nice值)等。

三、exec类函数介绍

unix提供了7个exec类函数,本小节将分别介绍这7种函数。

3.1 execl

头文件:#include <unistd.h>
函数原型:int execl(const char *path, const char
*arg0, …, (char *) NULL);
传入参数:
{
path:要执行的程序的路径。
arg0:新程序的第一个参数,通常是程序的名称(用于 argv[0])。
…:紧接着的参数列表,用于传递给新程序的其他参数,最后需要以NULL 结束。
}
返回值: 成功时,execl 不会返回,如果返回,通常表示出错。 出错时,返回 -1,并通过 errno设定相应的错误代码。

参考代码:

/*************************************************************************
        > File Name: exec_test.c
        > Author: conbiao
        > Created Time: 2024年09月29日 星期日 15时12分08秒
 ************************************************************************/

/***********************************************************************
 *                             HEADER
 **********************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>

/***********************************************************************
 *                              MACRO
 **********************************************************************/


/***********************************************************************
 *                          GLOBAL VARIABLE
 **********************************************************************/


/***********************************************************************
 *                       FUNCTION DESCRIPTION
 **********************************************************************/



/***********************************************************************
* FUNCTION NAME:
 ***********************************************************************
*
* Summary:
*
* Params:
*
* Return:
*
***********************************************************************/


/***********************************************************************
 *                                MAIN
 **********************************************************************/
int main(int argc, char *argv[])
{
    int ret = 0;
    pid_t pid;

    if((pid = fork()) < 0)
    {
        printf("fork fail!\n");
    }
    else if(pid == 0)
    {
        if(execl("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", "test", NULL) == -1)
        {
            printf("execl fail!\n");
        }
    }
    else
    {
        printf("This is father process! child's pid = %d\n",pid);
    }


    return ret;
}

需要调用的程序代码如下:

/*************************************************************************
        > File Name: test.c
        > Author: conbiao
        > Created Time: 2024年09月29日 星期日 15时16分00秒
 ************************************************************************/

/***********************************************************************
 *                             HEADER
 **********************************************************************/
#include<stdio.h>
#include<unistd.h>

/***********************************************************************
 *                              MACRO
 **********************************************************************/


/***********************************************************************
 *                          GLOBAL VARIABLE
 **********************************************************************/


/***********************************************************************
 *                       FUNCTION DESCRIPTION
 **********************************************************************/



/***********************************************************************
* FUNCTION NAME:
 ***********************************************************************
*
* Summary:
*
* Params:
*
* Return:
*
***********************************************************************/


/***********************************************************************
 *                                MAIN
 **********************************************************************/
int main(int argc, char *argv[])
{
    int ret = 0;

    while(1)
    {
        printf("This is %s!\n",__FILE__);
        sleep(1);
    }

    return ret;
}

运行结果如下所示:
在这里插入图片描述

(3.1-1)

3.2 execv

头文件:#include <unistd.h>
函数原型:int execv(const char *path, char *const
argv[]);
传入参数:
{
path:要执行的程序的路径。
argv:参数数组,包含新程序的参数列表。数组的第一个元素通常是程序名称(用于 argv[0]),最后一个元素必须是 NULL以标示参数列表的结束。
}
返回值: 成功时,execv 不会返回,如果返回,通常表示出错。 出错时,返回 -1,并通过 errno设定相应的错误代码。

参考代码如下:

/*************************************************************************
        > File Name: exec_test.c
        > Author: conbiao
        > Created Time: 2024年09月29日 星期日 15时12分08秒
 ************************************************************************/

/***********************************************************************
 *                             HEADER
 **********************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>

/***********************************************************************
 *                              MACRO
 **********************************************************************/
#define EXECV

/***********************************************************************
 *                          GLOBAL VARIABLE
 **********************************************************************/


/***********************************************************************
 *                       FUNCTION DESCRIPTION
 **********************************************************************/



/***********************************************************************
* FUNCTION NAME:
 ***********************************************************************
*
* Summary:
*
* Params:
*
* Return:
*
***********************************************************************/


/***********************************************************************
 *                                MAIN
 **********************************************************************/
int main(int argc, char *argv[])
{
    int ret = 0;
    pid_t pid;
#ifdef EXECV
    char *arg[] = {NULL};
#endif

    if((pid = fork()) < 0)
    {
        printf("fork fail!\n");
    }
    else if(pid == 0)
    {
#ifdef EXECL
        if(execl("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", "test", NULL) == -1)
        {
            printf("execl fail!\n");
        }
#elif defined(EXECV)
        if(execv("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", arg) == -1)
        {
            printf("execl fail!\n");
        }
#endif

    }
    else
    {
        printf("This is father process! child's pid = %d\n",pid);
    }


    return ret;
}

运行结果如下图所示:
在这里插入图片描述

(3.2-1)

3.3 execle

头文件:#include <unistd.h>
函数原型:int execle(const char *path, const char
*arg0, …, (char *) NULL, char *const envp[]);
传入参数:
{
path:要执行的程序的路径。
arg0:新程序的第一个参数,通常是程序的名称(用于 argv[0])。
…:紧接着的参数列表,用于传递给新程序的其他参数,最后需要以 NULL 结束。
envp: 一个指向环境变量字符串数组的指针,环境变量以
NULL 结尾。
}
返回值: 成功时,execv 不会返回,如果返回,通常表示出错。 出错时,返回 -1,并通过 errno设定相应的错误代码。 这个函数与上面两个的区别就是能够设置环境变量。

参考代码如下:

/*************************************************************************
        > File Name: exec_test.c
        > Author: conbiao
        > Created Time: 2024年09月29日 星期日 15时12分08秒
 ************************************************************************/

/***********************************************************************
 *                             HEADER
 **********************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>

/***********************************************************************
 *                              MACRO
 **********************************************************************/
//#define EXECV
#define EXECLE

/***********************************************************************
 *                          GLOBAL VARIABLE
 **********************************************************************/


/***********************************************************************
 *                       FUNCTION DESCRIPTION
 **********************************************************************/



/***********************************************************************
* FUNCTION NAME:
 ***********************************************************************
*
* Summary:
*
* Params:
*
* Return:
*
***********************************************************************/


/***********************************************************************
 *                                MAIN
 **********************************************************************/
int main(int argc, char *argv[])
{
    int ret = 0;
    pid_t pid;
#ifdef EXECV
    char *arg[] = {NULL};
#endif

#ifdef EXECLE
    char *envp[] = {"AUTHER=Conbiao",NULL};
#endif

    if((pid = fork()) < 0)
    {
        printf("fork fail!\n");
    }
    else if(pid == 0)
    {
#ifdef EXECL
        if(execl("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", "test", NULL) == -1)
        {
            printf("execl fail!\n");
        }
#elif defined(EXECV)
        if(execv("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", arg) == -1)
        {
            printf("execl fail!\n");
        }
#elif defined(EXECLE)
        if(execle("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", "test",NULL,envp) == -1)
        {
            printf("execl fail!\n");
        }
#endif

    }
    else
    {
        printf("This is father process! child's pid = %d\n",pid);
    }


    return ret;
}

test.c添加获取环境变量的操作,代码如下:

/*************************************************************************
        > File Name: test.c
        > Author: conbiao
        > Created Time: 2024年09月29日 星期日 15时16分00秒
 ************************************************************************/

/***********************************************************************
 *                             HEADER
 **********************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

/***********************************************************************
 *                              MACRO
 **********************************************************************/


/***********************************************************************
 *                          GLOBAL VARIABLE
 **********************************************************************/


/***********************************************************************
 *                       FUNCTION DESCRIPTION
 **********************************************************************/



/***********************************************************************
* FUNCTION NAME:
 ***********************************************************************
*
* Summary:
*
* Params:
*
* Return:
*
***********************************************************************/


/***********************************************************************
 *                                MAIN
 **********************************************************************/
int main(int argc, char *argv[])
{
    int ret = 0;

    printf("<%s> Author is: %s\n",__FILE__,getenv("AUTHER"));

    while(1)
    {
        printf("This is %s!\n",__FILE__);
        sleep(1);
    }

    return ret;
}

运行结果如下所示:
在这里插入图片描述

(3.3-1)

3.4 execve

头文件:#include <unistd.h>
函数原型:int execve(const char *path, char *const
argv[], char *const envp[]);
传入参数:
{
path:要执行的程序的路径。
argv:参数数组,包含新程序的参数列表。数组的第一个元素通常是程序名称(用于 argv[0]),最后一个元素必须是 NULL以标示参数列表的结束。
envp: 一个指向环境变量字符串数组的指针,环境变量以 NULL 结尾。
}
返回值: 成功时,execv不会返回,如果返回,通常表示出错。 出错时,返回 -1,并通过 errno 设定相应的错误代码。

这个函数其实就是将一个个参数以字符串数组的形式传入而已,在此就不做过多的介绍了。

3.5 execlp

头文件:#include <unistd.h>
函数原型:int execlp(const char *file, const char
*arg0, …, (char *) NULL);
传入参数:
{
file:要执行的程序的名称。该名称可以是相对路径或可执行文件的名称,execlp 函数会在环境变量 PATH 指定的目录中搜索该程序。
arg0:新程序的第一个参数,通常是程序的名称(用于 argv[0])。 …: 后续参数,用于传递给新程序的其他参数,最后需要以NULL 结束。
}
返回值: 成功时,execv 不会返回,如果返回,通常表示出错。 出错时,返回 -1,并通过 errno设定相应的错误代码。

参考代码如下:

/*************************************************************************
        > File Name: exec_test.c
        > Author: conbiao
        > Created Time: 2024年09月29日 星期日 15时12分08秒
 ************************************************************************/

/***********************************************************************
 *                             HEADER
 **********************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>

/***********************************************************************
 *                              MACRO
 **********************************************************************/
//#define EXECV
//#define EXECLE
#define EXECLP
/***********************************************************************
 *                          GLOBAL VARIABLE
 **********************************************************************/


/***********************************************************************
 *                       FUNCTION DESCRIPTION
 **********************************************************************/



/***********************************************************************
* FUNCTION NAME:
 ***********************************************************************
*
* Summary:
*
* Params:
*
* Return:
*
***********************************************************************/


/***********************************************************************
 *                                MAIN
 **********************************************************************/
int main(int argc, char *argv[])
{
    int ret = 0;
    pid_t pid;
#ifdef EXECV
    char *arg[] = {NULL};
#endif

#ifdef EXECLE
    char *envp[] = {"AUTHER=Conbiao",NULL};
#endif

    if((pid = fork()) < 0)
    {
        printf("fork fail!\n");
    }
    else if(pid == 0)
    {
#ifdef EXECL
        if(execl("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", "test", NULL) == -1)
        {
            printf("execl fail!\n");
        }
#elif defined(EXECV)
        if(execv("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", arg) == -1)
        {
            printf("execl fail!\n");
        }
#elif defined(EXECLE)
        if(execle("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", "test",NULL,envp) == -1)
        {
            printf("execl fail!\n");
        }
#elif defined(EXECLP)
        if(execlp("ls","-l",NULL) == -1)
        {
            printf("execl fail!\n");
        }
#endif

    }
    else
    {
        printf("This is father process! child's pid = %d\n",pid);
    }


    return ret;
}

运行结果如下:
在这里插入图片描述

(3.5-1)

3.6 execvp

头文件:#include <unistd.h>
函数原型:int execvp(const char *file, char *const
argv[]);
传入参数:
{
file:要执行的程序的名称。该名称可以是相对路径或仅是可执行文件的名称,execvp 会在环境变量PATH 指定的目录中搜索该程序。
argv:参数数组,包含新程序的参数列表。数组的第一个元素通常是程序名称(用于argv[0]),最后一个元素必须是 NULL 以标示参数列表的结束。
}
返回值: 成功时,execv 不会返回,如果返回,通常表示出错。出错时,返回 -1,并通过 errno 设定相应的错误代码。

该函数的功能与execv类似,就不做过多的介绍了。

3.7 fexecve

头文件:#include <unistd.h>
函数原型:int fexecve(int fd, char *const argv[],
char *const envp[]);
传入参数: { fd:一个文件描述符,指向要执行的可执行文件。这个文件描述符必须是通过 open系统调用以读执行模式打开的。
argv:参数数组,包含新程序的参数列表。数组的第一个元素通常是程序名称(用于argv[0]),最后一个元素必须是 NULL 以标示参数列表的结束。
envp: 一个指向环境变量字符串数组的指针,环境变量以 NULL结尾。
}
返回值: 成功时,execv 不会返回,如果返回,通常表示出错。 出错时,返回 -1,并通过 errno 设定相应的错误代码。

参考代码如下:

/*************************************************************************
        > File Name: exec_test.c
        > Author: conbiao
        > Created Time: 2024年09月29日 星期日 15时12分08秒
 ************************************************************************/

/***********************************************************************
 *                             HEADER
 **********************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
#include<fcntl.h>
/***********************************************************************
 *                              MACRO
 **********************************************************************/
//#define EXECV
//#define EXECLE
//#define EXECLP
#define FEXECVE
/***********************************************************************
 *                          GLOBAL VARIABLE
 **********************************************************************/


/***********************************************************************
 *                       FUNCTION DESCRIPTION
 **********************************************************************/



/***********************************************************************
* FUNCTION NAME:
 ***********************************************************************
*
* Summary:
*
* Params:
*
* Return:
*
***********************************************************************/


/***********************************************************************
 *                                MAIN
 **********************************************************************/
int main(int argc, char *argv[])
{
    int ret = 0;
    pid_t pid;
#ifdef FEXECVE
    char *arg[] = {NULL};
#endif

#ifdef FEXECVE
    char *envp[] = {"AUTHER=Conbiao",NULL};
#endif

    if((pid = fork()) < 0)
    {
        printf("fork fail!\n");
    }
    else if(pid == 0)
    {
#ifdef EXECL
        if(execl("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", "test", NULL) == -1)
        {
            printf("execl fail!\n");
        }
#elif defined(EXECV)
        if(execv("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", arg) == -1)
        {
            printf("execl fail!\n");
        }
#elif defined(EXECLE)
        if(execle("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", "test",NULL,envp) == -1)
        {
            printf("execl fail!\n");
        }
#elif defined(EXECLP)
        if(execlp("ls","-l",NULL) == -1)
        {
            printf("execl fail!\n");
        }
#elif defined(FEXECVE)
        int fd = open("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test",O_EXCL | O_RDONLY);
        if(fd == -1)
        {
            printf("open file fail!\n");
        }
        else
        {
            if(fexecve(fd,arg,envp) == -1)
            {
                printf("fexecve fail!\n");
            }
        }
#endif

    }
    else
    {
        printf("This is father process! child's pid = %d\n",pid);
    }


    return ret;
}

运行结果如下:
在这里插入图片描述

(3.7-1)

参考资料:

《UNIX环境高级编程(第3版) (史蒂文斯 (W.Richard Stevens) 拉戈 (Stephen A.Rago))
(Z-Library)》

标签:函数,exec,int,pid,char,unix,printf,test,NULL
From: https://blog.csdn.net/weixin_48344581/article/details/142640826

相关文章

  • Excel:常用函数
    一、DAYS(返回两个日期之间的天数)以下演示是在windows操作系统环境,office软件进行操作的1.1单元格设置日期格式1.2设置Days函数公式:=DAYS(C2,B2)全部天数二、SUM(求和)公式:=SUM(B2:C2)三、SUMIFS(多条件求和)3.1统计销售部报销金额公式:=SUMIFS(D:D......
  • wait_event_interruptible_timeout() 函数
     原文链接:https://blog.csdn.net/wuyongpeng0912/article/details/45723657 网上有关于此函数的分析,但大都是同一篇文章转载来转载去,没有进一步的分析。做个小结:了解函数功能,除了直接看代码逻辑,最有效的当是注释内容了。如下:函数原型:wait_event_interruptible_timeout......
  • MySQL窗口函数总结(三)
    MySQL窗口函数(WindowFunctions)是一种高级的SQL查询技巧,它允许在结果集的一组相关行上执行计算。窗口函数可以用于处理分组、排序、累计等复杂的聚合任务,使得查询更加简洁和高效。在MySQL8.0及更高版本中,支持窗口函数。以下是一些常用的窗口函数:ROW_NUMBER():为结果集中的......
  • MySQL窗口函数汇总(二)
    MySQL窗口函数详解MySQL从8.0版本开始引入了窗口函数,这是一个强大的特性,可以大大简化复杂的数据分析任务。本文将详细介绍MySQL窗口函数的概念、语法和常见用法,并结合实际应用场景进行说明。什么是窗口函数?窗口函数是一种能够对结果集中的一组行进行操作的函数。它们类似于聚合函......
  • 在线性坐标系中绘制二次函数图象
    本文记述了用Matplotlib在线性坐标系中绘制二次函数图象的例子。代码主体内容如下:...defmain():fig,axs=plt.subplots(1,3,figsize=(14,4.5))#1axs[0]=configure_axes(axs[0],'QuadraticFunction\t\t\t'+r'$\Delta>0$',18,18,10,......
  • PbootCMS在阿里云主机上邮件发送失败:服务器已经禁用stream_socket_client和fsockopen
    当你遇到PBootCMS网站的留言邮件通知功能失效,并且提示“服务器已经禁用 stream_socket_client 和 fsockopen 函数,请至少开启一个才能发送邮件!”时,这通常是因为服务器的安全策略禁用了这些函数。解决方法如下:步骤1:检查服务器配置登录阿里云主机管理后台:登录阿里云控制台......
  • 【C语言】qsort库函数
    使用qsort排数组升序:代码:#include<stdio.h>#include<stdlib.h>intcmp_int(constvoid*e1,constvoid*e2){ return*(int*)e1-*(int*)e2;}//使用qsort排升序voidtest1(){ intarr[]={9,8,7,6,5,4,3,2,1,0}; intsz=sizeof(arr)/sizeof(arr[0]); ......
  • 掌握Python的hasattr()函数
    掌握Python的hasattr()函数在Python编程中,hasattr()函数是一个非常实用的内置函数,它允许我们动态地检查一个对象是否拥有某个属性。这个功能在编写灵活、可扩展的代码时尤为重要,特别是在处理不确定的对象或需要兼容多种类型的对象时。本文将详细介绍hasattr()函数的基本用法、高......
  • linux系统下信号的概念以及相关操作函数(如何产生、捕捉信号)
    1.信号的概念信号在我们的生活中随处可见,如:古代战争中摔杯为号;现代战争中的信号弹;体育比赛中使用的信号枪......他们都有共性:1.简单2.不能携带大量信息3.满足某个特设条件才发送。信号是信息的载体,Linux/UNIX环境下,古老、经典的通信方式,现下依然是主要的通信手段。U......
  • python内置模块typing里Literal函数的基本用法和总结--快速学习掌握Literal函数的用法
    Literal是Pythontyping模块中提供的一种类型注解,用于指定变量或函数的参数只能取特定的字面量值(常量)。它允许你将变量的取值严格限制在指定的一组值内,确保程序只接受特定的常量值,从而减少错误的发生。一、基本概念在Python中,通常我们会使用常见的类型注解来限制变量......