/*
#include <stdlib.h>
void exit(int status);
#include <unistd.h>
void _exit(int status);
status 参数:是进程退出时的一个状态信息。父进程回收子进程资源的时候可以获取到。
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
printf("hello\n"); //内部自动刷新缓冲区的功能。标准 C 库的函数都是带有缓冲区的
printf("world\n"); ///数据在缓冲区里面,没有刷新缓冲区
// exit(0); //调用标准 C 库函数,他会刷新 IO 缓冲区
_exit(0); //系统调用,不会刷新 IO 缓冲区
return 0;
}
#include <sys/types.h>#include <unistd.h>#include <stdio.h>int main() {// 创建子进程pid_t pid = fork(); // 进程之间独立的// 判断是父进程还是子进程// 父进程先结束,原本的父进程应该是该进程// 父进程结束后,其父进程编程 initpid 是 1if(pid > 0) {printf("i am parent process, pid : %d, ppid : %d\n", getpid(), getppid());} else if(pid == 0) {sleep(1); // 子进程后结束// 当前是子进程printf("i am child process, pid : %d, ppid : %d\n", getpid(),getppid()); }// for 循环for(int i = 0; i < 3; i++) {printf("i : %d , pid : %d\n", i , getpid());}return 0;}
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main() {
// 创建子进程
pid_t pid = fork();
// 判断是父进程还是子进程
if(pid > 0) {
while(1) {//父进程很忙,不回收子进程
printf("i am parent process, pid : %d, ppid : %d\n", getpid(), getppid());
sleep(1);
}
} else if(pid == 0) {
// 当前是子进程
printf("i am child process, pid : %d, ppid : %d\n", getpid(),getppid());
}
// for 循环
for(int i = 0; i < 3; i++) {
printf("i : %d , pid : %d\n", i , getpid());
}
return 0;
}
/*
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *wstatus);
功能:等待任意一个子进程结束,如果任意一个子进程结束了,次函数会回收子进
程的资源。
一次性只能回收一个子进程的资源,如果有多个子进程,得调用多次
参数:int *wstatus
进程退出时的状态信息,传入的是一个 int 类型的地址,传出参数。
返回值:
- 成功:返回被回收的子进程的 id
- 失败:-1 (所有的子进程都结束,调用函数失败)
调用 wait 函数的进程会被挂起(阻塞),直到它的一个子进程退出或者收到一个不能
被忽略的信号时才被唤醒(相当于继续往下执行)
如果没有子进程了,函数立刻返回,返回-1;如果子进程都已经结束了,也会立即返回,
返回-1. */
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
// 有一个父进程,创建 5 个子进程(兄弟)
pid_t pid;
// 创建 5 个子进程
for(int i = 0; i < 5; i++) {
pid = fork();
if(pid == 0) {
break;
}
}
if(pid > 0) {
// 父进程
while(1) {
printf("parent, pid = %d\n", getpid());
// int ret = wait(NULL);
int st;
int ret = wait(&st);//父进程在这里阻塞
//根据 st 参数可以确定进程是如何被杀死的,exit()是正常退出
//如果是 kill -9 这是信号异常杀死
if(ret == -1) {
break;
}
/*捕获子进程是怎么退出的,子进程结尾是 exit(0),则状态码是 0,
如果子进程结尾是 exit(1),则状态码是 1*/
if(WIFEXITED(st)) {
// 是不是正常退出
printf("退出的状态码:%d\n", WEXITSTATUS(st));
}
/*通过 kill -9 将子进程杀死,就会打印,捕获子进程是怎么死亡的,是
异常终止*/
if(WIFSIGNALED(st)) {
// 是不是异常终止
printf("被哪个信号干掉了:%d\n", WTERMSIG(st));
}
printf("child die, pid = %d\n", ret);
sleep(1);
}
} else if (pid == 0){
// 子进程
while(1) {
printf("child, pid = %d\n",getpid());
sleep(1);
}
exit(0);
}
return 0; // 相当于 exit(0)
}
/*parent 只打印一次,因为 wait 是一个阻塞的函数
kill -9 四个子进程之后,
child, pid = 74922
child, pid = 74923
child, pid = 74924
parent, pid = 74921
child, pid = 74925
child, pid = 74926
child, pid = 74922
child, pid = 74923
child, pid = 74924
child, pid = 74925
child, pid = 74926
child, pid = 74923
child, pid = 74922
child, pid = 74924
child, pid = 74925
child, pid = 74926
child die,pid 74922
child die,pid 74923
child die,pid 74924
child die,pid 74925
回收子进程的时候,返回 子进程的 pid 号
当没有子进程的时候,wait 返回-1
*/
/*
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *wstatus, int options);
功能:回收指定进程号的子进程,可以设置是否阻塞。
参数:
- pid:
pid > 0 : 某个子进程的 pid
pid = 0 : 回收当前进程组的所有子进程
例如终端是一个进程,进程号是 33276
运行了一个程序,进程号是
ps ajx
PPID PID 组 ID 会 话 号 终 端
进程的名称
59468 76656 76656 59468 pts/0 76656 S+ 0 0:00
man 2 exit
76656 76666 76656 59468 pts/0 76656 S+ 0 0:00
pager
pid = -1 : 回收所有的子进程,相当于 wait() (最常用)
pid < -1 : 某个进程组的组 id 的绝对值,回收指定进程组中的子进程
- options:设置阻塞或者非阻塞
0 : 阻塞
WNOHANG : 非阻塞,是非阻塞的,该进程可以做其他事情
- 返回值:
> 0 : 返回子进程的 id
= 0 : options=WNOHANG, 表示还有子进程或者
= -1 :错误,或者没有子进程了
*/
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
// 有一个父进程,创建 5 个子进程(兄弟)
pid_t pid;
// 创建 5 个子进程
for(int i = 0; i < 5; i++) {
pid = fork();
if(pid == 0) {
break;
}
}
if(pid > 0) {
// 父进程
while(1) {
printf("parent, pid = %d\n", getpid());
sleep(1);
int st;
// int ret = waitpid(-1, &st, 0);
int ret = waitpid(-1, &st, WNOHANG);
if(ret == -1) {
break;
} else if(ret == 0) {
// 说明还有子进程存在
continue;
} else if(ret > 0) {
if(WIFEXITED(st)) {
// 是不是正常退出
printf("退出的状态码:%d\n", WEXITSTATUS(st));
}
if(WIFSIGNALED(st)) {
// 是不是异常终止
printf("被哪个信号干掉了:%d\n", WTERMSIG(st));
}
printf("child die, pid = %d\n", ret);
}
}
} else if (pid == 0){
// 子进程
while(1) {
printf("child, pid = %d\n",getpid());
sleep(1);
}
exit(0);
}
return 0;
}