父子进程
1. 退出关系
- 子进程继承了父进程的内容
- 父子进程有独立的地址空间, 互不影响
若父进程先结束
子进程成为孤儿进程,被init进程收养 ——》 子进程变成后台进程
若子进程先结束 ——》 父进程如果没有及时回收,子进程变成僵尸进程
2. 执行位置
fork 创建了子进程后,子进程从何处执行?
子进程从fork的下一条语句开始执行
父子进程谁先执行?
不确定,看操作系统先调度谁
3. 进程回收函数 —— wait
#include <unistd.h>
pid_t wait(int * status);
成功时返回回收的子进程的进程号;失败时返回EOF
若子进程没有结束,父进程一直阻塞
若有多个子进程,哪个子进程先结束就先回收
(有多少个子进程,就应该有多少个wait)status
指定保存子进程返回值和结束方式的地址status
为Null
, 直接释放子进程PCB,不接收返回值
int void main(int argc, const char * argv[])
{
int status;
pid_t pid;
if((pid ==fork()) < 0){
perror("fork");exit(-1);
}else if(0 == pid){
sleep(1);exit(2);
}else{
wait(&status);
printf("%x\n", status);
}
}
进程返回值和结束方式
子进程通过exit/_exit/return
返回某个值(0-255)
父进程调用wait(&status)回收
WIFEXITED(status) //判断子进程是否正常结束
WEXITSTATUS(status) 获取子进程返回值
WIFSIGNALEN(status) 判断子进程是否被信号结束
WTERMSIG(status) 获取结束子进程的信号类型
status[15: 0]
[6:0]为0 表示正常结束
大于0 表示结束子进程的信号类型
[15:8] 子进程返回值
进程回收函数 —— waitpid
#include<unistd.h>
pid_t waitpid(pid_t pid, int * status, int option);
成功时返回回收的子进程的pid或0;失败时返回EOF
pid 可用于指定回收哪个子进程或任意子进程
status 制定用于保存子进程返回值和结束方式的地址
option指定回收方式,0或WNOHANG
eg: waitpid(pid, &status, 0);
以阻塞方式回收指定子进程
waitpid(pid, &status, WNOHANG);
以非阻塞方式回收指定子进程(子进程没有结束返回0)
waitpid(-1, &status, 0) 等价于wait
waitpid(-1,&status, WNOHANG);
进程结束 exit / _exit
#include <stdlib.h>
#include <unistd.h>
void exit(int status); stdlib.h
void _exit(int status);
结束当前的进程并将status 返回
exit结束时会刷新(流)缓冲区
exec函数族
进程调用exec函数族执行某个程序,进程当前内容被指定的程序替换
实现让父子进程执行不同的程序
- 父进程创建子进程
- 子进程调用exec函数族
- 父进程不受影响
应用举例: shell
#include <unistd.h>
int execl(const char *path, const char * arg, ...);
int execlp(const char *file, const char * arg, ...);
成功时执行指定的程序; 失败时返回EOF
path 执行的程序的名称, 包含路径
arg... 传递给执行程序的参数列表
file 执行的程序的名称,在PATH中查找
eg: if(execl("/bin/ls", "ls","-a", "-l", "/etc", NULL )<0)
{
perror("execl");
}
if(execlp("ls", "ls","-a", "-l", "/etc", NULL )<0)
{
perror("execl");
}
int execv(const char * path, char * const argv[] );
int execvp(const char * file, char * const argv[] );
//成功时执行指定的程序; 失败时返回EOF
eg;char * arg[] = {"ls", "-a", "-l", "/etc",NULL};
if(execv("bin/ls", arg) < 0)
{
perror(execv);
}
if(execv("ls", arg) < 0)
{
perror(execvp);
}
system
#include <stdlib.h>
int system(const char * command);
调用此进程先创建子进程,执行完后返回当前进程
成功时返回command的返回值, 失败时返回EOF
当前进程等待command执行结束后才继续执行