![](https://i-blog.csdnimg.cn/blog_migrate/f693238965036cfcf93c4fc8071a76bd.png)
启动新进程
stdlib.h
int
system(const char *string)
which
equals to “sh -c string”
替换进程映像
unistd.h
char
**environ;
int
execl(const char *path, const char *arg0, ...(char *)0);
int
execlp(const char *file, const char *arg0, ...(char *)0);
int
execle(const char *path, const char *arg0,
...,(char
*)0, char * const envp[]);
这三个函数的参数个数是可变的,
参数以一个空指针结束。
int
execv(const char *path, char *const argv[]);
int
execvp(const char *file, char *const argv[]);
这两个函数的第二个参数是一个字符串数组,新程序在启动时,会把在argv[]数组中给定的参数传递给main函数。
int
execve(const char *filename, char *const argv[],
char *const
envp[]);
//int
execvpe(const char *file, char *const argv[],
char *const envp[]);
以字母p结尾的函数通过搜索PATH环境变量来查找新程序的可执行文件路径。若可执行文件不在PATH定义的路径中,就需要把包括目录在内的使用绝对路径的文件名作为参数传递给函数。
全局变量environ可以把一个值传递到新的程序环境中。
execle和execve可以通过参数envp传递字符串数组作为新程序的环境变量。
由exec类函数启动的进程,他的参数表和环境加在一起的总长度是有限的ARG_MAX(posix
> 4096B,linux = 128kb)。错误返回errno
复制进程映像
让进程同时执行多个函数,可以使用线程或从源程序中创建一个完全分离的进程(类似于init)
fork复制当前进程,创建出来的新进程和原进程几乎一样,但新进程有自己的数据空间,环境,fd。和exec函数结合使用。
![](https://i-blog.csdnimg.cn/blog_migrate/8494227b077d671cdb0ef97f63122758.png)
sys/types.h
unistd.h
pid_t
fork(void);
fork失败返回-1,通常因为父进程所用有的子进程数目超限(CHILD_MAX),此时errno被设置为EAGAIN;若进程表没有足够的空间用于创建新的表单或虚拟内存不足,errno为ENOMEM
11.3.1等待一个进程
在父进程中调用wait让父进程等待子进程的结束。
sys/types.h
sys/wait.h
pid_t
wait(int *stat_loc);
若stat_loc不是空指针,状态信息将被写入它所指向的位置。
11.3.2
僵尸进程
子进程终止时,它与父进程之间的关系还会保持,直到父进程也正常终止或父进程调用wait才告结束。因此进程表中代表子进程的表项不会立刻释放,以备父进程今后的wait调用,这时它将成为一个死进程zombie
若父进程异常终止,子进程自动会把pid=1的init作为父进程。僵尸进程将一直保留在进程表中直到被init发现并释放。
sys/types.h
sys/wait.h
pid_t
waitpid(pid_t pid, int *stat_loc,int options);
pid指定需要等待的子进程pid;和wait一样,若stat_loc不是空指针,状态信息将被写入它所指向的位置;options可用来改变waitpid的行为,如WNOHANG,防止waitpid将调用者执行挂起,其他选项和wait相同。
![](https://i-blog.csdnimg.cn/blog_migrate/eaef36e97d527aa1bd3edee5988307b8.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3c1a2afe30826a6a2f565054ffba1b1b.png)