Chapter XIII Process (5)

Replace exec process image

In the process of creating the Unix uses a unique approach, which will process creates and loads a new process image separation. The advantage is that there is more room for the two operations management.
When we create a process, the child process usually replaced with a new process image, which can be used to perform the function exec series. Of course, the series can also be a function exec will replace the current process.

 

exec family of functions

Header file <unistd.h>
function can be replaced with the current process exec function as a new process. exec name is a complete series consists of multiple correlation function of composition

原型
     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[]);
参数
    * path参数表示你要启动程序的名称包括路径名
    * arg参数表示启动程序所带的参数
    * 带'l'的表示可变参数列表(argument list(仅仅自己理解方便记忆))
    * 带'v'的表示参数是(char* argv[](仅仅自己理解方便记忆))
    * 带‘p'的表示 会从环境变量中搜索是否有这个程序存在
    * 带’e'的表示 会传一个环境信息
返回值:
    * 成功  0
    * 失败  -1

 

Code segment, the data segment is replaced, after the code will not be executed

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

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)


int main(int argc, char *argv[])
{
    printf("Entering main ...\n");
    execlp("ls","ls","-hl",NULL);
    printf("Exiting main ...\n");
    return 0;
}

 
Replace a process does not modify the original process id

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

int main(void)
{
    printf("pid : %d\n",getpid());
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)


int main(int argc, char *argv[])
{
    printf("Entering main ...\n");
    printf("before replace pid : %d\n",getpid());
    //代码段、数据段被替换
    //int ret = execlp("./hello","hello",NULL);

    //linux默认情况下是在环境变量(echo $PATH)下搜索源程序
    int ret = execlp("hello","hello",NULL);
    if(ret == -1)
        perror("execlp error");
    printf("Exiting main ...\n");
    return 0;
}

 

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

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)


int main(int argc, char *argv[])
{
    char* const args[] = {"ls","-l",NULL};
    printf("Entering main ...\n");

    "第一个参数可以是绝对路径,也可以是相对路径,也可以不带路径"
    //int ret = execlp("ls","ls","-l",NULL);
    int ret = execvp("ls",args);
    if(ret == -1)
        perror("execlp error");

    printf("Exiting main ...\n");
    return 0;
}

 
Example 1

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

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)


int main(int argc, char *argv[])
{
    printf("Entering main ...\n");

    //带'p'的表示会从环境变量或指定的路径获取文件
    //execlp("ls","ls","-hl",NULL);

    char *const args[] = {"ls", "-hl", NULL};
    //execvp("ls", args);

    // 并不会在环境变量中搜索,这个地方必须给出一个路径(相对路径和绝对路径都可以)
    //int ret = execv("ls", args);
    //int ret = execl("ls","ls","-hl",NULL);
    if( ret < 0 )
    {
        perror("execl");
    }

    printf("Exiting main ...\n");
    return 0;
}

 
Example 2

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

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)


int main(int argc, char *argv[])
{
    printf("Entering main ...\n");

    //execl执行hello,会将当前的环境信息传递给hello,
    //而当前进程的环境信息,是从shell中继承下来的

    //简单的说,就是执行“execl”这个程序的的时候,shell会被做为参数,传递到进程中,
    //在进程中又调用execl,执行"hello"这个程序,“execl”又将shell作为参数传递到“hello"这个进程中
    /* int ret = execl("./hello", "hello", NULL);
    if(ret == -1)
    {
        perror("execl");
    } */

    //设置自己的环境变量信息
    char* const envp[] = {"AA=1", "BB=2", NULL};
    int ret = execle("./hello", "hello", NULL, envp);
    if(ret == -1)
    {
        perror("execl");
    }

    printf("Exiting main ...\n");
    return 0;
}

 
Example 3

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

//全部变量,C库中已存在,此处声明下就可以
extern char** environ;

int main(int argc, char const *argv[])
{
   printf("hello! pid = %d\n",getpid());
   int i;
   for(i=0; environ[i] != NULL; ++i)
   {
      printf("%s\n",environ[i]);
   }

   return 0;
}


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

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)


int main(int argc, char *argv[])
{
    printf("Entering main ...\n");

    /*
    man 2 fcntl;
    File descriptor flags
       The following commands manipulate the flags associated with a file descriptor.  Currently, only one such flag
       is defined: FD_CLOEXEC, the close-on-exec flag.  If the FD_CLOEXEC bit is 0, the file descriptor will  remain
       open across an execve(2), otherwise it will be closed.
    */
   //如果将一个文件描述符设置为FD_CLOEXEC,当我们调用execve进行替换的时候,文件描述符会被关闭 

    int ret = fcntl(1, F_SETFD, FD_CLOEXEC);//置1
    if(ret == -1)
    {
        perror("fcntl");
    }

    //execlp替换成功,但是因为设置了FD_CLOEXEC,调用hello的时候,1号文件描述符被关闭了,所以”hello"程序无法输出
    //对于open()函数,在打开文件的时候,我们可以加O_CLOEXEC,表示将FD_CLOEXEC置为1,当调用exec系列会自动关闭文件描述符
    ret = execlp("./hello", "hello", NULL);
    if(ret == -1)
    {
        perror("execl");
    }

    printf("Exiting main ...\n");
    return 0;
}

Guess you like

Origin www.cnblogs.com/s3320/p/11397380.html