创建进程可以用fork()和vfork()函数,二者用法类似
/*NAME
fork - create a child process
*/
//SYNOPSIS
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
/*RETURN VALUE
On success, the PID of the child process is returned in the parent, and
0 is returned in the child. On failure, -1 is returned in the parent,
no child process is created, and errno is set appropriately.
*/
fork()函数调用成功返回两次
返回值为0 代表当前进程是子进程
返回值为非负数 代表当前进程是父进程
调用失败,返回-1
二者之间的区别:
关键区别1:vfork()直接使用父进程存储空间,不进行拷贝
关键区别2:vfork()保证子进程先运行,当子进程调用exit退出后,父进程才执行。
进程退出:(不管进程如何终止,最后都会执行内核中同一段代码。这段代码为相应进程关闭所有打开描述符,释放它所使用的存储器等)
正常退出
1.main函数调用return
2.进程调用exit(),标准C库
3.进程调用_exit()或者_Exit(),属于系统调用
补充:
1.进程最后一个线程返回
2.最后一个线程调用pthread_exit()
异常退出
1.调用abort()
2.当进程调用某些信号时,如Ctrl+C
3.最后一个线程对取消(cancellantion)请求作出响应
父进程等待子进程退出并收集子进程退出状态
/*status参数:是一个整形数指针
非空:子进程退出状态,放在它所指向的地址中
空:不关心退出状态
*/
NAME
wait, waitpid, waitid - wait for process to change state
SYNOPSIS
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
/* This is the glibc and POSIX interface; see
NOTES for information on the raw system call. */
表8-1 检查wait和waitpid所返回的终止状态的宏
宏 | 说明 |
WIFEXITED(status) | 若为正常终止子进程返回的状态,则为真。对于这种情况可执行WEXITSTATUS(status),取子进程传送给exit、_exit或_Exit参数的低8位 |
WIFSIGNALED(status) | 若为异常终止子进程返回的状态,则为真(接到一个不捕捉的信号)。对于这种情况,可执行WTERMSIG(status),取使子进程终止的信号编号。另外,有些实现定义宏WCOREDUMP(status),若已产生终止进程的core文件,则它返回真 |
WIFSTOPPED(status) | 若为当前暂停子进程的返回状态,则为真。对于这种情况,可执行WSTOPSIG(status),取使子进程暂停的信号编号 |
WIFCONTINUED(status) | 若在作业控制暂停后已经继续的子进程返回了状态,则为真。(POSIX.1的XSI扩展;仅用于waitpid。) |
子进程退出状态不被收集,变成僵死进程(僵尸进程)
孤儿进程
父进程如果不等待子进程的退出,在子进程之前就结束了自己的“生命”,此时子进程叫做孤儿进程
Linux为了避免系统存在过多的孤儿进程,init进程收留孤儿进程,变成孤儿进程的父进程