创建进程:fork/exec

简介: #include int execl(const char *path, const char *arg, ...);int execlp(const char *file, const char *arg, .

#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: \n");
         // 执行/bin目录下的ls, 第一参数为程序名ls, 第二个参数为"-al", 第三个参数为"/etc/passwd"
         execl("/bin/ls", "ls", "-al", "/etc/passwd", (char *) 0);
         
         //system("ls -a");
         _exit(127);
     }
     else
     {
         printf("father: 11\n");
         while(waitpid(pid, &status, 0) < 0)
         {
             if(errno != EINTR)
             {
                 status = -1;
                 break;
             }
         }
         printf("father: 22\n");
     }
     
     return status;
 } 

#endif

 

 

目录
相关文章
|
8月前
|
C语言
C语言 父进程fork()出的多个子进程在结束后,父进程如何回收?
我在网上找了半天都是在说wait()和waitpid()的详解或者是单个子进程的回收。答非所问。 很简单,根据wait()或者waitpid()的函数特性。没有子进程时返回-1。
63 0
|
8月前
|
Unix Linux C++
111 python高级 - 进程的创建fork
111 python高级 - 进程的创建fork
26 0
|
9月前
|
算法 Linux Shell
Linux:进程的本质和fork初识
Linux:进程的本质和fork初识
|
22天前
|
算法 Linux 调度
Linux进程——进程的创建(fork的原理)
Linux进程——进程的创建(fork的原理)
15 2
|
2月前
|
Linux Shell 程序员
【进程控制】进程程序替换的原理以及exec函数族
【进程控制】进程程序替换的原理以及exec函数族
|
2月前
|
存储 算法 Unix
【创建进程】fork函数与写时拷贝
【创建进程】fork函数与写时拷贝
|
2月前
|
Linux Shell 调度
【Linux系列】fork( )函数原理与应用详解——了解【父子进程及其特性】(代码演示,画图帮助理解,思维导图,精简)(11)
【Linux系列】fork( )函数原理与应用详解——了解【父子进程及其特性】(代码演示,画图帮助理解,思维导图,精简)(11)
|
2月前
|
算法 Linux Shell
【linux进程(二)】如何创建子进程?--fork函数深度剖析
【linux进程(二)】如何创建子进程?--fork函数深度剖析
|
2月前
|
Java Linux Shell
进程的程序替换(exec函数)【Linux】
进程的程序替换(exec函数)【Linux】