15. C语言的fork

创建子进程:

fork();

"fork"翻译成中文叫:分叉,表示当执行了一次fork()后,会将当前内存数据拷贝一份出来,后续代码执行时候分叉了,即在父进程和子进程里都会执行。

因此在后续代码中如何判断当前的分支是父进程还是哪个子进程就显得尤为重要,尤其是当父进程和子进程需要执行不同后续代码的时候。

子进程里再创建子进程,本文暂不做探讨。

如何使用fork()创建多个同级的子进程¶

创建1个子进程

fork();

创建2个子进程

pid_t child1_pid;

pid_t child2_pid;

child1_pid = fork();

if (child1_pid > 0) {

child2_pid = fork();

}

可以简写为

if (fork() > 0) {

fork()

}

创建3个子进程

pid_t child1_pid;

pid_t child2_pid;

pid_t child3_pid;

child1_pid = fork();

if (child1_pid > 0) {

child2_pid = fork();

}

if (child1_pid > 0 && child2_pid > 0) {

child3_pid = fork();

}

创建4个子进程

pid_t child1_pid;

pid_t child2_pid;

pid_t child3_pid;

pid_t child4_pid;

child1_pid = fork();

if (child1_pid > 0) {

child2_pid = fork();

}

if (child1_pid > 0 && child2_pid > 0) {

child3_pid = fork();

}

if (child1_pid > 0 && child2_pid > 0 && child3_pid > 0) {

child4_pid = fork();

}

如何定位到指定的同级子进程或者父进程¶

执行fork();会返回该子进程的pid(pid_t类型的数字)

当"我是子进程"的时候,我的pid为0

当"我是父进程"的时候,我之前产生的所有子进程pid均大于0

因此可以通过上面3个特点来综合判断"我是谁",详见本章节-完整例子

单核和多核的区别¶

分别在单核和多核上执行,观察每次执行输出的顺序是否一致,详见本章节-完整例子

父进程先退出,子进程会消失吗¶

在代码最后加上sleep(1);来观察(同时可以结合单核和多核分别测试),详见本章节-完整例子

完整例子¶

实验环境:分别在1核和4核linux服务器上测试C语言的fork

完整代码

#include

#include

main() {

// 主要是为了

pid_t child1_pid;

pid_t child2_pid;

pid_t child3_pid;

pid_t child4_pid;

// 创建4个同级的子进程

child1_pid = fork();

if (child1_pid > 0) {

child2_pid = fork();

}

if (child1_pid > 0 && child2_pid > 0) {

child3_pid = fork();

}

if (child1_pid > 0 && child2_pid > 0 && child3_pid > 0) {

child4_pid = fork();

}

// 定位到指定的子进程或者父进程

if (child1_pid * child2_pid * child3_pid * child4_pid != 0) {

printf("I'm parent: pid=%d ppid=%d child1_pid=%d child2_pid=%d child3_pid=%d child4_pid=%d\n", getpid(), getppid(), child1_pid, child2_pid, child3_pid, child4_pid);

}

else if (child1_pid == 0) {

printf("I'm child1: pid=%d ppid=%d child1_pid=%d child2_pid=%d child3_pid=%d child4_pid=%d\n", getpid(), getppid(), child1_pid, child2_pid, child3_pid, child4_pid);

}

else if (child2_pid == 0) {

printf("I'm child2: pid=%d ppid=%d child1_pid=%d child2_pid=%d child3_pid=%d child4_pid=%d\n", getpid(), getppid(), child1_pid, child2_pid, child3_pid, child4_pid);

}

else if (child3_pid == 0) {

printf("I'm child3: pid=%d ppid=%d child1_pid=%d child2_pid=%d child3_pid=%d child4_pid=%d\n", getpid(), getppid(), child1_pid, child2_pid, child3_pid, child4_pid);

}

else if (child4_pid == 0) {

printf("I'm child4: pid=%d ppid=%d child1_pid=%d child2_pid=%d child3_pid=%d child4_pid=%d\n", getpid(), getppid(), child1_pid, child2_pid, child3_pid, child4_pid);

}

else {

printf("ERROR\n");

}

sleep(1);

}

分别在单核和多核情况下执行上面代码(gcc -o fork fork.c && ./fork),同时观察有无sleep(1)这行的区别,对比结果:

单核运行结果:

有sleep(1)

I'm parent: pid=4801 ppid=3226 child1_pid=4802 child2_pid=4803 child3_pid=4804 child4_pid=4805

I'm child4: pid=4805 ppid=4801 child1_pid=4802 child2_pid=4803 child3_pid=4804 child4_pid=0

I'm child3: pid=4804 ppid=4801 child1_pid=4802 child2_pid=4803 child3_pid=0 child4_pid=-1

I'm child2: pid=4803 ppid=4801 child1_pid=4802 child2_pid=0 child3_pid=-1 child4_pid=-1

I'm child1: pid=4802 ppid=4801 child1_pid=0 child2_pid=-1 child3_pid=-1 child4_pid=-1

多次测试,会发现这5行的前后顺序固定

无sleep(1)

I'm parent: pid=5095 ppid=3226 child1_pid=5096 child2_pid=5097 child3_pid=5098 child4_pid=5099

I'm child4: pid=5099 ppid=1 child1_pid=5096 child2_pid=5097 child3_pid=5098 child4_pid=0

I'm child3: pid=5098 ppid=1 child1_pid=5096 child2_pid=5097 child3_pid=0 child4_pid=-1

I'm child2: pid=5097 ppid=1 child1_pid=5096 child2_pid=0 child3_pid=-1 child4_pid=-1

I'm child1: pid=5096 ppid=1 child1_pid=0 child2_pid=-1 child3_pid=-1 child4_pid=-1

多次测试,会发现这5行的前后顺序固定

注意看上面的ppid,所有child的ppid均为1,是因为父进程一执行完就退出了,而此时子进程还未执行完,随即子进程被过继给操作系统管理(init进程成为继父,pid为1)

多核运行结果:

有sleep(1)

I'm child1: pid=10586 ppid=10585 child1_pid=0 child2_pid=-1 child3_pid=-1 child4_pid=-1

I'm parent: pid=10585 ppid=3316 child1_pid=10586 child2_pid=10587 child3_pid=10588 child4_pid=10589

I'm child4: pid=10589 ppid=10585 child1_pid=10586 child2_pid=10587 child3_pid=10588 child4_pid=0

I'm child3: pid=10588 ppid=10585 child1_pid=10586 child2_pid=10587 child3_pid=0 child4_pid=-1

I'm child2: pid=10587 ppid=10585 child1_pid=10586 child2_pid=0 child3_pid=-1 child4_pid=-1

多次测试,会发现这5行的前后顺序不定

无sleep(1)

I'm child1: pid=10787 ppid=10786 child1_pid=0 child2_pid=-1 child3_pid=-1 child4_pid=-1

I'm child2: pid=10788 ppid=10786 child1_pid=10787 child2_pid=0 child3_pid=-1 child4_pid=-1

I'm parent: pid=10786 ppid=3316 child1_pid=10787 child2_pid=10788 child3_pid=10789 child4_pid=10790

I'm child4: pid=10790 ppid=10786 child1_pid=10787 child2_pid=10788 child3_pid=10789 child4_pid=0

I'm child3: pid=10789 ppid=10786 child1_pid=10787 child2_pid=10788 child3_pid=0 child4_pid=-1

多次测试,会发现这5行的前后顺序不定

有时候还会像下面这样结果,即多个ppid为1

I'm child1: pid=11443 ppid=11442 child1_pid=0 child2_pid=-1 child3_pid=-1 child4_pid=-1

I'm child2: pid=11444 ppid=11442 child1_pid=11443 child2_pid=0 child3_pid=-1 child4_pid=-1

I'm parent: pid=11442 ppid=3316 child1_pid=11443 child2_pid=11444 child3_pid=11445 child4_pid=11446

I'm child3: pid=11445 ppid=1 child1_pid=11443 child2_pid=11444 child3_pid=0 child4_pid=-1

I'm child4: pid=11446 ppid=1 child1_pid=11443 child2_pid=11444 child3_pid=11445 child4_pid=0

在代码运行中pstree -p的输出如下

fork(16242)─┬─fork(16243)

├─fork(16244)

├─fork(16245)

└─fork(16246)

注意观察输出中的child{1-4}.pid,可以看到

父进程里,4个child的pid都是有值的

子进程child1里,child1_pid为0,其他child_pid都为初始值-1

子进程child2里,child1_pid有值,child2_pid为0,其他child_pid都为初始值-1

子进程child3里,child1_pid有值,child2_pid有值,child3_pid为0,其他child_pid都为初始值-1

子进程child4里,child1_pid有值,child2_pid有值,child3_pid有值,child4_pid为0

如果创建同级更多子进程,可以以此类推。通过这个特性来确定当前处于父进程还是某个子进程

c语言文件io的fork,15. C语言的fork相关推荐

  1. C语言 文件IO的使用

    简单介绍C语言文件操作函数的用法(可以直接使用): fopen fclose fprintf fscanf fputc fgetc fread fwrite 头文件 #include<stdio ...

  2. c语言文件加密解密单词统计,C语言文件加密解密及单词统计程序.doc

    C语言文件加密解密及单词统计程序.doc (10页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 15.9 积分  高级语言程序设计 课程设计学 院 计算 ...

  3. c语言文件pt是什么意思,C语言文件p的pt.ppt

    C语言文件p的pt ● 格式读函数一般形式为 fscanf(文件指针,格式控制,地址表) 从指定的文件中按格式读数据. 必须指出的是,fprintf() 函数与fscanf()函数是对应的,即在使用 ...

  4. c语言文件写入函数有哪些,c语言文件读写函数有哪些?

    c语言文件读写函数有:"fgetc"和"fputc"(字符读写函数)."fgets"和"fputs"(字符串读写函数). ...

  5. Linux下 C语言文件IO操作(系统IO)

    Linux系统下使用C语言进行文件系统IO操作 1打开文件 函数:int open(const char *,int flags); //打开一个已经存在的文件 int open(const char ...

  6. c语言文件制作错题集,C语言错题集

    指针 1.char *s="C Language";表示s是一个指向字符串的指针变量,把字符串的首地址赋予s. (1分) T 2.C 语言是一种具有某些低级语言特征的高级语言. ( ...

  7. 按平均成绩排行c语言文件操作,学生成绩管理系统(c语言结构体以及文件操作)实验报告精选.doc...

    学生成绩管理系统(c语言结构体以及文件操作)实验报告精选 C程序设计 实验报告 编号: 姓名院系学号任课教师于萧指导教师实验地点实验时间实验名称文件操作同 组 人无预习报告(对实验主要内容的认识)得分 ...

  8. C语言文件读取错误怎么解决,c语言中文件随机读取出错如何解决

    在一个链表中找出相同的结点的算法与之相似,不过对于文件来说有点烦. 因为在C语言中对流式文件进行操作时,打开文件后,有一个读写位置指针,记录的是读写时在文件中的位置,其初始状态与打开方式有关.r.r+ ...

  9. c语言文件按字节读取整数,C语言逐行读取文件

    C语言可以说是我学习的第一门语言,不过似乎也是忘的最多的一门语言,自从因为项目需要重新拾起C语言,我的噩梦就开始了. 依稀记得大二学习数据结构时编程解决"约瑟夫环"."迷 ...

  10. c语言文件读写r 的作用,C语言 读写二进制文件

    查找了比较多的资源, 发现没有办法把text 文件转成binary文件 仅作为记录,不过这个例子可以去除换行符.#include #include #define N 255 int main() { ...

最新文章

  1. ajax合并表单,ajax。表单
  2. 【详细解读】进程管理 -死锁问题 系统有三个进程:A B C 这3个进程都需要5个系统资源。如果系统至少有多少个资源,则不可能发生死锁
  3. MyEclipse 如何使用断点调试
  4. 【英语】秋风吹---9月英语
  5. Linux计划任务之_Crontab
  6. subst 的使用 创建虚拟盘符
  7. CRM WEB UI 01 BOL向导创建的搜索
  8. 语音助手——简介与交互过程
  9. 学习神经网络:搭建一个vgg-11模型在FashionMNIST训练
  10. python用for循环求和1到100_python使用for循环计算0-100的整数的和方法
  11. Centos搭建服务
  12. OLTP与OLAP理解
  13. 解决Win11连接群晖上的L2TP类型无响应的问题
  14. tEST 1 for NOIP 2017.9.9.
  15. 【python】PyQt6和pyqt6-tools在PyCharm2021的详细配置方法
  16. echart 的各大国家城市坐标
  17. python图片转文字easyocr_OCR识别软件将图片转文字的具体方法
  18. 0018-量化第五天:QMT—日内回转回测注释
  19. Excel IF 函数多条件判断
  20. DNAT(目的地址转换)-IP映射和端口映射

热门文章

  1. 6.Composer实现PHP中类的自动加载
  2. 3. PSR-3 --- 日志接口
  3. 4. laravel 路由(1)
  4. css3中的transform中的3d变换:translatez()与transform-origin-z()的区别
  5. [django]django model的查询和更新
  6. python的进程和线程
  7. react中IOS手机里面两个input同时存在时,聚焦focus失效解决办法
  8. My Calendar I
  9. 【Maven】运行项目
  10. Form窗体点击关闭按钮并未关闭进程的解决方法