实操(等待子进程)Linux
相关函数
1. fork()
- 功能:创建一个新的子进程,子进程是父进程的副本(复制代码、数据段、堆栈等)
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
返回值:
成功时父进程返回子进程的 PID(>0)
子进程返回 0
失败时返回 -1(如进程数达到限制)
2. getpid()、 getppid()
-
功能:获取当前进程的PID(进程ID)、PPID(父进程ID)
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
返回值:当前进程的PID(始终成功)
pid_t getppid(void);
返回值:当前进程的PPID(若父进程已终止,返回系统初始化进程的PID,如 init 或 systemd)
4. sleep(unsigned int seconds)
-
功能:使当前进程休眠指定秒数(可能被信号中断)。
#include <unistd.h>
unsigned int sleep(unsigned int seconds);
参数:seconds——休眠的秒数
返回值:
成功休眠完毕返回 0
被信号中断时返回剩余的秒数
5. exit(int status)
-
功能:终止当前进程,并返回状态码给父进程(通过
wait/waitpid
获取)
#include <stdlib.h>
void exit(int status);
参数:status——退出状态(低8位可被父进程捕获)
6. waitpid(pid_t pid, int status, int options)
-
功能:等待指定子进程的状态变化(如终止或暂停)
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *wstatus, int options);
参数:
pid:
>0:等待指定PID的子进程。
-1:等待任意子进程(等价于 wait)。
0:等待与调用进程同组的子进程。
<-1:等待进程组ID为 |pid| 的任意子进程。
status:输出子进程的终止状态(需用宏如 WIFEXITED 解析)。
options:
0:阻塞等待
WNOHANG:非阻塞,若无子进程退出则立即返回。
返回值:
成功时返回 子进程PID。
WNOHANG 且无子进程退出时返回 0。
失败时返回 -1(如无子进程)。
7. WIFEXITED(int status)
-
功能:检查子进程是否正常退出(通过
exit
或return
)。
参数:status——waitpid 获取的退出状态
返回值:
若正常退出返回 非0值(true)
否则返回 0
8. WEXITSTATUS(int status)
-
功能:提取子进程的退出状态码(
exit
或return
的值)。
参数:status——waitpid 获取的退出状态(需先通过 WIFEXITED 检查)
返回值:子进程的退出状态码(低8位,范围 0-255)
实操
test.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#define TASK_NUM 10
typedef void (*func_t)();
func_t other_task[TASK_NUM];
void a() { printf("正在执行a任务\n"); }
void b() { printf("正在执行b任务\n"); }
void c() { printf("正在执行c任务\n"); }
int LoadTask(func_t func)
{
int i = 0;
for(; i < TASK_NUM; ++i) if (other_task[i] == NULL) break;
if (i == TASK_NUM) return -1;
else other_task[i] = func;
return 0;
}
void InitTask()
{
for(int i = 0; i < TASK_NUM; ++i) other_task[i] = NULL;
LoadTask(a);
LoadTask(b);
LoadTask(c);
}
void RunTask()
{
for(int i = 0; i < TASK_NUM; ++i)
{
if (other_task[i] == NULL) continue;
else other_task[i]();
}
}
int main()
{
pid_t id = fork();
if (id == 0)
{
int cnt = 10;
while(cnt)
{
printf("我是子进程,我还能跑%ds, pid: %d, ppid: %d\n", cnt--, getpid(), getppid());
sleep(1);
int *p = NULL;
*p = 1;
}
exit(111);
}
InitTask();
while(1)
{
int status = 0;
pid_t ret_id = waitpid(id, &status, WNOHANG);
if (ret_id < 0)
{
printf("waitpid error\n");
exit(1);
}
else if (ret_id == 0)
{
RunTask();
sleep(1);
continue;
}
else
{
if (WIFEXITED(status))
printf("wait succcess, child exit code: %d\n", WEXITSTATUS(status));
else
printf("wait succcess, child exit signal: %d\n", status & 0x7F);
break;
}
}
return 0;
}