• 创建进程:fork/exec


    #include <unistd.h>
    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[]);

    1、上述exec系列函数底层都是通过execve系统调用实现:
    execve() executes the program pointed to by filename. filename must be either a binary executable, or a script starting with a line of the form
    2、带L的exec函数:execl,execlp,execle,表示后边的参数以可变参数的形式给出且都以一个空指针结束。
    3、带 p 的exec函数:execlp,execvp,表示第一个参数path不用输入完整路径,只有给出命令名即可,它会在环境变量PATH当中查找命令

    4、vfork保证子进程先运行,在它调用exec或exit之后父进程才可能被调度运行。如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。

    5、fork要拷贝父进程的进程环境;而vfork则不需要完全拷贝父进程的进程环境,在子进程没有调用exec和exit之前,子进程与父进程共享进程环境,相当于线程的概念,此时父进程阻塞等待。

    6、为什么会有vfork呢?
    因为以前的fork当它创建一个子进程时,将会创建一个新的地址空间,并且拷贝父进程的资源,然后将会有两种行为:
    1.执行从父进程那里拷贝过来的代码段
    2.调用一个exec执行一个新的代码段

    当进程调用exec函数时,一个新程序替换了当前进程的正文,数据,堆和栈段。这样,前面的拷贝工作就是白费力气了,这种情况下,聪明的人就想出了vfork。vfork并不复制父进程的进程环境,子进程在父进程的地址空间中运行,所以子进程不能进行写操作,并且在儿子“霸占”着老子的房子时候,要委屈老子一下了,让他在外面歇着(阻塞),一旦儿子执行了exec或者exit后,相当于儿子买了自己的房子了,这时候就相当于分家了。
    因此,如果创建子进程是为了调用exec执行一个新的程序的时候,就应该使用vfork

    https://yq.aliyun.com/articles/48614

    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <string.h>
    #include <sys/syscall.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    
    /*
    #include <unistd.h>
    int execl(const char *pathname, const char *arg, …);
    int execlp(const char *filename,conxt char *arg, …);
    int execle(const char *pathname,conxt char *arg, …,char *const envp[ ]);
    int execv(const char *pathname, char *const argv[ ]);
    int execvp(const char *filename, char *const argv[ ]);
    int execve(const char *pathname, char *const argv[ ],char *const envp[ ]);
    
    #include <stdlib.h>
    int system(const char *cmdstring);
    
    #include <sched.h>
    int__clone(int (*fn)(void *arg),void *child_stack,int flags,void *arg);
    
    #include <stdlib.h>
    void exit(int status);
    int atexit(void (*function)(void));
    int on_exit(void(*function)(int, void*), void *arg);
    void abort(void);
    
    #include <unistd,h>
    void _exit(int status);
    
    #include <assert.h>
    void assert(int expression);
    
    */
    
    #ifndef T_DESC
    #define T_DESC(x, y)   (y)
    #endif
    
    
    #if T_DESC("global", 1)
    
    
    int main(int argc, char **argv)
    {
         pid_t pid;
         int status;
         
         if((pid = fork()) < 0)
         {
             status = -1;
         }
         else if(pid == 0)
         {
             printf("child: 
    ");
             // 执行/bin目录下的ls, 第一参数为程序名ls, 第二个参数为"-al", 第三个参数为"/etc/passwd"
             execl("/bin/ls", "ls", "-al", "/etc/passwd", (char *) 0);
             
             //system("ls -a");
             _exit(127);
         }
         else
         {
             printf("father: 11
    ");
             while(waitpid(pid, &status, 0) < 0)
             {
                 if(errno != EINTR)
                 {
                     status = -1;
                     break;
                 }
             }
             printf("father: 22
    ");
         }
         
         return status;
     } 
    
    #endif
  • 相关阅读:
    windows 启动关闭Oracle监听和服务
    自定义 Git
    c++ cmakelist 详解
    vue自定义错误界面
    C++ Web 编程
    前端如何将H5页面打包成本地app?
    django教程
    部署 Django
    Django 国际化和本地化
    Django与CSRF 、AJAX
  • 原文地址:https://www.cnblogs.com/soul-stone/p/6131223.html
Copyright © 2020-2023  润新知