操作系统 - Linux - 使用fork()函数实现三个进程并发执行
文章目录
这里三个进程是指父进程和两个子进程,也就是利用fork()
创建两个子进程
fork()
函数介绍
1. 函数原型
#include <unistd.h>
/* Clone the calling process, creating an exact copy.
Return -1 for errors, 0 to the new process,
and the process ID of the new process to the old process. */
extern __pid_t fork (void) __THROWNL;
大概意思就是:复制调用该函数的进程,创建一个相同的副本。出错返回-1,新进程(子进程)返回0,老进程(父进程)返回新进程(子进程)的PID。
2. 返回值
fork()
函数比较特殊,调用一次,返回两次
- 子进程接收到返回值为0
- 父进程接收到返回值为子进程的PID(大于0)
3. fork()
的使用
// fork()的使用
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
pid_t fpid;
if ((fpid = fork()) < 0)
{ // 出错
printf("fork faild\n");
exit(0);
}
else if (fpid == 0)
{ // 子进程执行
printf("Child process!\n");
// getpid()获取当前进程号, getppid()获取父进程号,fpid为fork()的返回值
printf("PPID=%d PID=%d FPID=%d\n", getppid(), getpid(), fpid);
// 进程正常终止
exit(0);
}
else
{ // 父进程执行
wait(NULL); // 父进程阻塞,等待子进程结束再继续执行
printf("Parent process!\n");
printf("PPID=%d PID=%d FPID=%d\n", getppid(), getpid(), fpid);
exit(0);
}
}
输出结果
Child process!
PPID=4198 PID=4203 FPID=0
Parent process!
PPID=4193 PID=4198 FPID=4203
结果分析
pid
- 当前进程号
ppid
- 父进程号
fpid
- fork()
返回值
- 子进程的FPID为0
- 父进程的FPID == 4203 == 子进程的PID == 4203
- 子进程的PPID == 3934 == 父进程的PID == 3934
- 注意
wait()
使用fork()
实现三个进程并发执行
1. 代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#define NUM 5 // print_msg()循环打印次数
void afterFork(int index, pid_t fpid);
void print_msg(int index, char *m);
int main(int argc, char *argv[])
{
int index = 0; // 自定义的当前进程序号,0表示父进程,从1开始表示第1个子进程
pid_t fpid_1 = fork(); // fork第一个子进程
afterFork(++index, fpid_1);
pid_t fpid_2 = fork(); // fork第二个子进程
afterFork(++index, fpid_2);
print_msg(0, "---"); // ---代表父进程
wait(NULL); // 等待所有子进程结束
return 0;
}
/**
* @brief 父进程执行fork()函数之后的操作
*
* @param index 自定义的进程序号,1表示第1个子进程,2表示第2个子进程
* @param fpid fork()的返回值
*/
void afterFork(int index, pid_t fpid)
{
if (fpid < 0)
{
printf("fork faild\n");
exit(0);
}
else if (fpid == 0)
{
print_msg(index, "***"); // ***代表子进程
exit(0); // 子进程退出
}
}
/**
* @brief 间隔1s打印信息,每个进程会循环打印NUM次
*
* @param index
* @param sign ---代表父进程,***代表子进程
*/
void print_msg(int index, char *sign)
{
int i;
for (i = 0; i < NUM; i++)
{
printf("%sindex=%d%s\n", sign, index, sign);
fflush(stdout);
sleep(1); // 等待1s
}
}
代码解释
- 没有判断
fpid > 0
的情况,因为我们要先创建两个子进程然后再执行父进程的代码,所以父进程的代码(print_msg()
)放在了程序末尾 - 注意子进程执行完毕后要
exit(0)
,否则子进程又会执行另一个fork()
函数再创建一个子进程中的子进程,就会各种套娃
2. 实现效果
可以看到,三个进程(几乎)是同时执行的,但是三个进程执行的前后顺序每次都可能发生变化(这也说明了确实是并发执行)