网站首页 > 基础教程 正文
前言 总结送福利
使用系统调用fork()创建三个子进程;
各个子进程显示和输出一些提示信息和自己的进程标识符;
父进程显示自己的进程ID和一些提示信息,然后调用waitpid()等待多个子进程结束,并在子进程结束后显示输出提示信息表示程序结束。
代码能说明问题
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
int tprintf(const char *fmt,...);
int main(void)
{
printf("I'm your father,PID is %d.\n",getpid());
pid_t pid = fork();
if(pid == 0){
printf("I'm a first son.PID is %d.\n",getpid());
exit(1);//若此处没有exit(1), 进程也会执行 pid_t pid2 = fork()语句,会出现孙进程
printf("You should never see this.\n");
}
pid_t pid2 = fork();
if(pid2 == 0){
printf("I'm a second son.PID is %d.\n",getpid());
exit(1);
printf("You should never see this.\n");
}
pid_t pid3 = fork();
if(pid3 ==0){
printf("I'm a third son.PID is %d.\n",getpid());
exit(1);
printf("You should never see this.\n");
}
else if(pid != -1){
tprintf("Parent forked child process--%d.\n",pid);
tprintf("Parent is waiting for child to exit.\n");
waitpid(pid,NULL,0);
waitpid(pid2,NULL,0);
waitpid(pid3,NULL,0);
tprintf("Child Process had exited.\n");
tprintf("Parent had exited.\n");
}
elsetprintf("Everything was done without error.\n");
return 0;
接下来问题就来了
fork的时候发生什么?
①执行到这一句的时候,一个进程被创建了,这个进程与父进程一样,拥有一套与父进程相同的变量,相同的一套代码,这里可以粗浅的理解为子进程又复制了一份main函数。这里返回一个子进程的进程号,大于0。(第一次fork)
②子进程怎么执行:
子进程从fork()的位置开始执行,也就是说前面的代码不走,但是拥有之前的变量以及变量的值,与父进程的值一样,这次fork(),返回值是0,所以在子进程里面直接执行了pid==0这一个分支,父进程里面并不执行这个分支的语句。这就为我们在写mian函数的时候怎么写子进程的程序提供了一个方法来隔离代码。
明白了这个原理之后我们再来看一段代码
*
* 设置输出格式
*/
int tprintf(const char* fmt,...)
{
va_list args;
struct tm *tstruct;
time_t tsec;
tsec = time(NULL);
tstruct = localtime(&tsec);
printf("%02d:%02d:%02d:%5d|",tstruct->tm_hour,tstruct->tm_min,tstruct->tm_sec,getpid());
va_start(args,fmt);
return vprintf(fmt,args);
运行结果
这里每一次输出表示一个进程的创建,可以看到一共有8个进程被创建,有兴趣的话可以验证一下连续四次fork可以出16个进程,但是不建议再多了,电脑会卡死,不要问我怎么知道的!
猜想是出2的n次方个进程。如果上面的第一段代码理解了的话,我们按照子进程从父进程fork的位置开始执行就会理解为什么会有八个进程。
这里附上思维导图助于理解
那么我们想创建不是2的n次方个进程应该怎么做呢?这里还是以三个为例
#include <stdio.h>
#include <stdlib.h>
#include <sys/unistd.h>
int main(int argc, char *argv[]) {
int i,j,status;
int pid[3];
for(i=0; i<3;i++){
if((pid[i]=fork()) >0){
printf("This is child process pid=%d\n",pid[i]);
} else{
printf("This is father process pid=%d\n",pid[i]);
exit( EXIT_SUCCESS);
}
}
return EXIT_SUCCESS;
}
总结
不是最准确的,可以与三次fork进行对比。
关注+后台私信;资料;两个字可以免费领取 资料内容包括:C/C++,Linux,golang,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,嵌入式 等。。。
猜你喜欢
- 2024-10-19 Python3 datetime模块指南:日期时间操作、时区管理与实战案例
- 2024-10-19 C++及数据结构复习笔记,类和对象很简单?为啥好多程序员还不会
- 2024-10-19 Linux时间和日期 linux 时间 表示方法
- 2024-10-19 C/C++的8种时间度量方式以及代码片段
- 2024-10-19 Python实战:使用 datetime模块处理时间日期的全方位指南
- 2024-10-19 C++编程的 42 条建议(四) c++编程100例
- 2024-10-19 mount with noatime - 合理关闭atime提高服务器性能
- 2024-10-19 C函数time和clock的计时区别 c计时器函数
- 2024-10-19 win进程弹出Microsoft Visual C++ Runtime Library的解决办法
- 2024-10-19 库函数——ctime()和ctime不安全函数
- 最近发表
- 标签列表
-
- gitpush (61)
- pythonif (68)
- location.href (57)
- tail-f (57)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- css3动画 (57)
- c#event (59)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- exec命令 (59)
- canvasfilltext (58)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- node教程 (59)
- console.table (62)
- c++time_t (58)
- phpcookie (58)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)