• linux c编程:进程控制(三)_exec函数


    fork()函数通过系统调用创建一个与原来进程(父进程)几乎完全相同的进程(子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述存储空间的“副本”,这意味着父子进程不共享这些存储空间。linux将复制父进程的地址空间内容给子进程,因此,子进程由了独立的地址空间。),也就是这两个进程做完全相同的事。
    在fork后的子进程中使用exec函数族,可以装入和运行其它程序(子进程替换原有进程,和父进程做不同的事
    exec函数族可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段。在执行完后,原调用进程的内容除了进程号外,其它全部被新程序的内容替换了。另外,这里的可执行文件既可以是二进制文件,也可以是Linux下任何可执行脚本文件。
    在Linux中使用exec函数族主要有一下两种情况
    当进程认为自己不能再为系统和用户做出任何贡献时,就可以调用任何exec函数族让自己重生;
    如果一个进程想执行另外一个程序,那么它就可以调用fork函数新建一个进程,然后调用任何一个exec函数使子进程重生
    实际上linux并没有exec函数,而是有6个exec开头的函数。函数用法如下:

    6个函数的区别如下:

    • 查找方式:上表中前4个函数的查找方式都是完整的文件目录路径(即绝对路径),而最后两个函数(也就是以p结尾的两个函数)可以只给出文件名,系统就会自动从环境变量“$PATH”所指出的路径中进行查找。
    • 参数传递方式:有两种方式,一种是逐个列举的方式,另一种是将所有参数整体构造成一个指针数组进行传递。(在这里,字母“l”表示逐个列举的方式,字母“v”表示将所有参数整体构造成指针数组进行传递,然后将该数组的首地址当做参数传递给它,数组中的最后一个指针要求时NULL
    • 环境变量:exec函数族使用了系统默认的环境变量,也可以传入指定的环境变量。这里以“e”结尾的两个函数就可以在envp[]中指定当前进程所使用的环境变量替换掉该进程继承的所有环境变量

    exec后新进程保持原进程以下特征 

    环境变量(使用了execleexecve函数则不继承环境变量);

    进程ID和父进程ID

    实际用户ID和实际组ID

    附加组ID

    进程组ID

    会话ID

    控制终端;

    当前工作目录;

    根目录;

    文件权限屏蔽字;

    文件锁;

    进程信号屏蔽;

    未决信号;

    资源限制;

    tms_utimetms_stimetms_cutime以及tms_ustime值。

    下面来看下实际的函数用法:

    下面的这个函数是执行shellls命令。由于使用execle因此指定了ls命令的路径/bin/ls

    void exec_function_try(){

        pid_t pid;

        if ((pid = fork()) < 0){

            printf("error");

        }

        else if (pid == 0){

            if(execle("/bin/ls","-al",(char *)0,env_init) < 0)

                printf("error for execle");

        }

    }

    运行结果。列出了当前工程目录下的所有文件

    上面的这个函数是执行shell命令。下面的这个函数执行的是另外一个c文件

    void exec_function(){

        pid_t pid;

        if ((pid = fork()) < 0){

            printf("error");

        }

        else if (pid == 0){

            if(execle("/home/zhf/c_prj/test","echoall","myarg1","MY ARG2",(char *)0,env_init) < 0)

                printf("error for execle");

        }

        

        if ((pid == fork()) < 0){

            printf("error");

        }

        else if (pid == 0){

            if(execlp("test","echoall","only 1 arg","MY ARG2",(char *)0) < 0)

                printf("error for execlp");

        }

        

    }

    test.c的代码如下:

    #include<stdlib.h>

    #include<stdio.h>

    int main(int argc,char *argv[]){

    int i;

    char **ptr;

    extern char **environ;

    for(int i=0;i<argc;i++)

    printf("argv[%d]:%s ",i,argv[i]);

    for(ptr=environ;*ptr!=0;ptr++)

    printf("%s ",*ptr);

    exit(0);

    }

    首先执行gcc -g -o test test.c生成可执行的test文件,然后在exec_function中就可以被引用。

    执行结果如下

  • 相关阅读:
    jenkins插件开发
    常用模块-------hashlib (加密模块)
    树莓派在任意无线网下连接笔记本(借用笔记本屏幕)
    常用模块-------时间模块(time/datetime),随机数模块(random)
    pycharm常用的快捷方式及设置
    迭代器
    生成器
    获取行业和概念列表
    钉钉页面扫码登录中hmac加密签名
    获取钉钉开发access_token
  • 原文地址:https://www.cnblogs.com/zhanghongfeng/p/9048424.html
Copyright © 2020-2023  润新知