-
2020-10-11 17:10:40
在使用fork()函数进行创建子线程的时候,如果没有在创建成功子进程时选择break跳出for循环,那么子进程也会进入for循环,开始调用fork()函数创建“孙子”进程,所以在创建子进程成功的时候就直接选择break跳出循环,使得if(pid == 0)为子进程的唯一出口,而父进程的唯一出口就是当for循环执行完毕后。
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<unistd.h> 4 int main(){ 5 pid_t pid; 6 int i; 7 for(i = 1; i < 5; i++){ 8 pid = fork(); 9 if(pid == -1){ 10 perror("fork创建进程失败!\n"); 11 }else if(pid == 0){ 12 //此处创建的是子进程,当遇到子进程的时候就跳出循环,免得再次循环执行fork()函数 13 break;//此处为子进程的唯一出口 14 } 15 } 16 17 //父进程的唯一出口为当循环执行结束后 18 if( i < 5){ 19 sleep(i); 20 printf("我是第%d个子进程,我的父进程id为%u\n",i+1,getppid()); 21 }else{ 22 sleep(i); 23 printf("我是父进程,我的pid为%d\n",getpid()); 24 } 25 }
更多相关内容 -
进程篇:循环创建N个子进程
2018-05-14 00:00:00进程篇:循环创建N个子进程 标签:fork();N个子进程 从前面的进程篇——fork()可以了解到fork函数会创建父进程和子进程,并且他们在执行的时候,怎么来控制说是先创建父进程,还是先创建子进程呢?其实根据...进程篇:循环创建N个子进程
标签:fork();N个子进程
从前面的进程篇——fork()可以了解到fork函数会创建父进程和子进程,并且他们在执行的时候,怎么来控制说是先创建父进程,还是先创建子进程呢?其实根据计算机原理来说,父子进程抢占cpu,谁先得到就谁先执行,其实也有一种说法,是父进程先执行的可能性比较大,但是没有理论依据。好了,费话不多说,我们来看代码。
首先,我们先看这样的一段代码:1 #include<stdio.h> 2 #include<unistd.h> 3 int main() 4 { 5 int i; 6 pid_t pid; 7 // for(i=0;i<5;i++) 8 // { 9 pid = fork(); 10 if(pid==-1) 11 perror("error\n"); 12 else if(pid==0) 13 printf("child,pid=%u,ppid=%u\n",getpid(),getppid()); 14 else{ 15 // sleep(1); 16 printf("father,pid=%u,ppid=%u\n",getpid(),getppid()); 17 } 18 // } 19 return 0; 20 21 }
这段代码其实很简单,但是大家看一下结果,就会有问题了:
从这个结果,我们可以看出的是,结果输出为什么会出现在命令行中,而不是像平时代码一样,执行完后出现命令行,但是这个确出现在了命令行。我们用命令查看一下,输入命令:ps aux | grep 2669
得到的结果是:
wz 2669 0.0 0.3 8512 3468 pts/0 Ss 10:21 0:00 bash wz 6391 0.0 0.0 6124 824 pts/0 S+ 20:41 0:00 grep --color=auto 2669
看到这个2669这个进程是bash进程的进程号: 所以产生上面的现象的原因是:
在产生这么多的子进程的时候,bash是不知道这么多的子进程和孙子进程的,在开始的shell命令行中,我们使用./fork的命令,然后shell进程把自己切入到后台,前台是给了fork程序来使用的,shell进程收回前台的命令是在它执行完之后,也就是儿子进程执行完之后,shell会收回前台,在父进程return之后,shell进程就把前台收回了,然后再进入命令行模式中,等待用户输入命令,所以会出现这样的情况,所以解决办法就是保证shell的子进程在最后结束。
好了,解决完上面的问题,我们来看循环子进程的问题。对于循环子进程来说,我们很容易就知道,我们需要fork()函数执行N次,我们用3次来模拟,代码如下:1 #include<stdio.h> 2 #include<unistd.h> 3 int main() 4 { 5 int i; 6 pid_t pid; 7 for(i=0;i<3;i++) 8 { 9 pid = fork(); 10 if(pid==-1) 11 perror("error\n"); 12 else if(pid==0) 13 printf("i am %dth child,pid=%u,ppid=%u\n",i+1,getpid(),getppid() ); 14 else{ 15 sleep(1); 16 printf("i am %dth father,pid=%u,ppid=%u\n",i+1,getpid(),getppid( )); 17 } 18 } 19 return 0; 20 21 }
得到的结果为:
i am 1th child,pid=7222,ppid=7221 i am 2th child,pid=7223,ppid=7222 i am 3th child,pid=7224,ppid=7223 i am 1th father,pid=7221,ppid=2669 i am 2th father,pid=7222,ppid=7221 i am 3th father,pid=7223,ppid=7222 i am 2th child,pid=7225,ppid=7221 i am 3th child,pid=7226,ppid=7222 i am 3th child,pid=7227,ppid=7225 i am 2th father,pid=7221,ppid=2669 i am 3th father,pid=7222,ppid=7221 i am 3th father,pid=7225,ppid=7221 i am 3th child,pid=7228,ppid=7221 i am 3th father,pid=7221,ppid=2669
看起来比较凌乱。但是为什么会出现这么多,我们通过一张图来看一下:
从这图很容易看出来子进程产生的过程。
上面的程序我们修改一下,就可以很准确的看到有几个子进程被创建:1 #include<stdio.h> 2 #include<unistd.h> 3 int main() 4 { 5 int i; 6 pid_t pid; 7 for(i=0;i<5;i++) 8 { 9 pid = fork(); 10 if(pid==-1) 11 perror("error\n"); 12 else if(pid==0) 13 { 14 break; 15 } 16 if(i<5) 17 { 18 sleep(i); 19 printf("i am %dth child\n",i+1); 20 } 21 else 22 { 23 sleep(i); 24 printf("i am parent\n"); 25 } 26 } 27 return 0; 28 29 }
结果为:
i am 1th child i am 2th child i am 3th child i am 4th child i am 5th child
这就看起来比较明显了。
-
fork 循环创建多个子进程
2020-08-25 10:01:40对于以下循环创建进程是什么样的呢? int i = 0; while(i < 3){ fork(); /*功能代码*/ i++; } 子进程创建如下图 学习笔记 对于仅含有一个 fork()的循环体,循环n次后,共有2^n个进程(包含最初始的父进程)...循环创建多个子进程
对于以下循环创建进程是什么样的呢?
int i = 0; while(i < 3){ fork(); /*功能代码*/ i++; }
子进程创建如下图
学习笔记
- 对于仅含有一个 fork()的循环体,循环n次后,共有2^n个进程(包含最初始的父进程);
- 若fork()在循环体的开端,循环体的代码将被执行 (2^(n+1)-2) 次;
- 事实上,我们一般只让父进程 fork,不让 子进程 继续fork,所以当 fork()返回值为0时,跳出循环,这样的话,循环n次,创建n个子进程;
练习
通过命令行参数指定创建进程的个数,每个进程休眠 1S 打印自己是第几个被创 建的进程。如:第 1 个子进程休眠 0 秒打印:“我是第 1 个子进程”;第 2 个进程休眠 1 秒打 印:“我是第 2 个子进程”;第 3 个进程休眠 2 秒打印:“我是第 3 个子进程”。
目标
通过该练习掌握框架:循环创建 n 个子进程,使用循环因子 i 对创建的子进程加以区分;
代码
#include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]){ int i, n, pid; i = 0; n = *argv[1]-'0'; while(i < n){ pid = fork(); if(!pid){ break; } i++; } sleep(i); if(!pid){ printf("I'm the %d child process.\n", i+1); }else if(pid > 0){ printf("I'm the parent process %d.\n", i); } return 0; }
注:
- 每个子程序都不会执行i++;
运行结果
2020/07/24 13:03
@luxurylu -
循环创建N个子进程
2019-03-25 17:14:42以循环创建5个进程为例,给出如下代码,分析其错误: #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(void) { int i; pid_t pid; printf("xxxxxxxxxxx\n"); for ...以循环创建5个进程为例,给出如下代码,分析其错误:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(void) { int i; pid_t pid; printf("xxxxxxxxxxx\n"); for (i = 0; i < 5; i++) { pid = fork( ); if(pid == -1) { printf("process of %u creat process failurely!\n",getpid( )); perror("fork"); } else if(pid == 0) { printf("I'am %dth child , pid = %u\n", i+1, getpid()); } else { printf("I'am parent, pid = %u\n",getpid()); } } printf("yyyyyyyyyy\n"); return 0; }
分析:首先在shell中执行该文件时,由终端进程fork产生一个子进程来执行该程序,然后在for循环体中,子进程在创建一个个的孙进程。在上述for循环体中,i=0时,父进程创建了一个子进程,此时父进程与子进程的i都为0(刚fork后两个的i相等,但是以后不一定相等,它们各自独立)。此时有两个进程(父、子进程)都会开始向下执行,即后面的代码都一样的执行,各个进程一直执行到return语句后,各个进程才会自动终止(结束)。上述,在for循环体中创建的子进程,又会在下一次循环中继续去创建子进程,因此最终并不仅仅创建的是5个进程,而是共创建了25-1个进程,总共25个进程。如果循环n次,则总共为2n个进程。
因此,需要在循环的过程,保证子进程不再执行fork ,因此当(fork() == 0)时,子进程应该立即break;才正确(即跳出循环体)。
练习:通过命令行参数指定创建进程的个数,如:第1个子进程休眠0秒打印:“我是第1个子进程”;第2个进程休眠1秒打印:“我是第2个子进程”;第3个进程休眠2秒打印:“我是第3个子进程。”
通过该练习掌握框架:循环创建n个子进程,使用循环因子i对创建的子进程加以区分。
//代码如下:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char *argv[ ]) { if(argc < 2) { printf("./a.out 5\n"); exit(1); } int i; pid_t pid; printf("xxxxxxxxxxx\n"); long int a = strtol(argv[1],NULL,10); //将字符串转化为10进制整数 for (i = 0; i < a; i++) { pid = fork( ); //创建子进程 if(pid == -1) { printf("process of %u creat process failurely!\n",getpid( )); perror("fork"); } //判断创建进程是否成功,如果当次循环创建不成功,则不结束该进程,进行下一次循环,再次尝试创建(这样等效于少了一次循环)。 else if(pid == 0) //如果为子进程,则跳出循环 { break; } else //否则(父进程),不执行操作,进入下一次循环 ; } sleep(i); //通过i值来区分进程,可见父进程睡眠时间最久,为a秒,最先创建的子进程睡眠时间最少,为0秒。 if(i < 5) printf("I'am the %dth child process, the ID = %u\n",i+1,getpid( )); //子进程输出 else printf("I'am parent process, the ID = %u\n",getpid( )); //父进程输出 return 0; }
[root@localhost fork]# ./fork_test 5 //shell终端fork产生子进程来运行这一程序
xxxxxxxxxxx
I'am the 1th child process, the ID = 16507
I'am the 2th child process, the ID = 16508
I'am the 3th child process, the ID = 16509
I'am the 4th child process, the ID = 16510
I'am the 5th child process, the ID = 16511
I'am parent process, the ID = 16506
[root@localhost fork]#
分析:之所以要引入sleep函数,来使各个进程睡眠,是为了确保父进程最后结束(即最后执行return),且越先创建的子进程越先能够结束。而在创建进程后,每个进程的i值都由自己维护,都要从创建处开始执行自己的代码,从而i值发生改变。因此就可以用i来区分是哪一个进程,从而越先创建的进程睡眠时间越少,第i个子进程睡眠时间为i-1秒。下面深度分析sleep函数,代码如下:
//与上面的代码相比,只是去掉了一行内容: sleep(i); 因此不再列出,其执行结果如下:
[root@localhost fork]# ./fork_test 5
xxxxxxxxxxx
I'am parent process, the ID = 16702
I'am the 3th child process, the ID = 16705
[root@localhost fork]# I'am the 1th child process, the ID = 16703
I'am the 2th child process, the ID = 16704
I'am the 5th child process, the ID = 16707
I'am the 4th child process, the ID = 16706
pwd //正常执行shell中的pwd命令(前面标签已经输出)
/mnt/hgfs/share/01_process_test/fork
[root@localhost fork]#
分析:由上可以看出,在没有sleep( )函数的控制下,每个进程的结束先后顺序是随机的,没法控制的。在上述程序执行过程中,总共参与了7个进程:shell终端进程、父进程(由shell终端fork产生)和5个子进程(由父进程fork产生),这7个进程对CPU的抢占是公平的(随机的),无法预测。注意一点:父进程只能够知道其子进程是否结束,而不能直到其孙进程是什么状态,这7个进程共同使用这一个终端,当shell中执行. /fork_test 5时,shell进程会把前台交给其子进程使用,一旦子进程结束(执行了return后),shell进程知道并马上收回前台,并输出[root@localhost fork]# 光标 等待与用户再次交互(此时shell进程放弃了CPU,将自己阻塞起来,等待用户的命令),但是此时那5个子进程并不一定就结束了,因此未结束的进程将会继续占用CPU,直到执行到return并结束。因此,这些进程的输出结果会在 [root@localhost fork]#的后面。CPU在1s内可执行上亿条指令,因此睡1s可以绝对保证进程可以按照希望的顺序执行。
-
WINDOWS创建进程
2014-05-04 09:26:30基于Windows的进程建立程序,不过是全英文版 -
fork函数讲解和运用(循环创建n个子进程)
2019-05-08 23:01:21fork函数用于创建一个子进程 用法 #include <unistd.h> pid_t fork(void); 对于父进程来说,fork函数返回成功返回子进程id,对于子进程来说,fork函数成功返回0;失败返回-1; C/C++中的函数返回值只能有一个... -
linux实验报告\操作系统进程创建父子进程实验报告.docx
2013-02-09 15:17:29dLinux进程创建与进程通信,实现父进程创建一个子进程,返回后父子进程分别循环输出字符串“The parent process.”及“The child process.”5次,每次输出后使用sleep(10)延时10秒,然后再进入下一次循环。... -
多进程之父进程创建10个子进程
2021-05-28 09:30:33//每次循环时,如果发现是子进程就直接从创建子进程的循环中跳出来,不让你进入循环,这样就保证了每次只有父进程来做循环创建子进程的工作 } if(status==-1) { //error } elseif(status==0)//每个子进程都会... -
《Linux操作系统》进程管理
2019-12-09 22:53:361.进程的属性保存在一个被称为的结构体中,这个结构体包括、进程组、进程环境、进程的运行状态等。 2.进程在内存中可能会出现不同的状态,通常进程的状态被划分为5种:初始态、、、和终止态。 3.Linux系统中的进程... -
操作系统之Windows 进程管理中的创建子进程
2019-07-11 17:24:28创建子进程:本实验显示了创建子进程的基本框架。该程序只是再一次地启动自身,显示它的系统进程 ID和它在进程列表中的位置。 步骤 1:创建一个“Win32 Consol Application”工程,然后可复制下面中的程序,编译成... -
【Linux】进程控制 —— 进程创建 | 进程退出 | 进程等待 | 进程程序替换 | 实现简易shell
2022-04-10 15:06:43例如子进程从fork返回后,调用exec*函数(进程替换马上详谈) fork调用失败的原因 众所周知,创建进程成本很高(时间+空间),系统中有太多进程时,资源不足 用户创建的进程数超出了限制,为了防止某些用户恶意创建。... -
Linux进程分析(三) fork循环创建Linux子进程
2018-08-30 19:49:54fork fork的意思是复制进程,就是把当前的程序再加载一次,...返回值为pid_t,实际是unsigned int:子进程中为0,父进程中为子进程ID,出错则为-1。 开始写了几个都不成功,最后终于成功了: pid_t p = getpid(... -
〖Python语法进阶篇③〗- 进程的创建与常用方法
2022-04-08 02:10:29该章节我们来学习一下在 Python 中去创建并使用多进程的方法,通过学习该章节,我们将可以通过创建多个进程来帮助我们提高脚本执行的效率。可以认为缩短脚本执行的时间,就是提高执行我们脚本的效率。接下来让我们都... -
Linux-进程控制详解(进程创建+进程终止+进程等待+进程程序替换)
2020-12-01 14:31:27而这个新创建出来的进程被称为原进程的子进程,原进程被称为该进程的父进程。 该函数其实是一个系统调用接口,原型如下: #include <unistd.h> pid_t fork(void); 特性:子进程会复制父进程的PCB,二者之间... -
父进程创建五个子进程
2020-05-17 11:38:40父进程创建五个子进程 #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/wait.h> int main() { pid_t pid; int i; for(i=0;i<5;i++) { if((pid=fork())==... -
进程和线程的创建 _实验报告.doc
2019-06-18 17:31:58这个程序创建一个子进程,执行an_ch2_1b。这个程序不断地输出如下行: Those output come from child,[系统时间] 观察程序运行的结果,并对你看到的现象进行解释。 2.在linux环境下编写一个控制台应用程序,程序中有... -
Linux创建进程链、进程扇、进程树
2021-01-09 22:54:13如何创建进程链、进程扇、进程树 -
实验三 进程的创建
2021-06-06 20:40:11练习使用 EOS API 函数 CreateProcess 创建一个进程,掌握创建进程的方法,理解进程和程序的区别。 \2. 调试跟踪 CreateProcess 函数的执行过程,了解进程的创建过程,理解进程是资源分配的基本单位。 \3. 调试跟踪... -
循环中fork创建进程的个数
2015-06-07 09:35:05linux下创建进程的系统调用是fork。...在循环中创建进程时,进程的个数是怎样的? 1、循环中没有任何父子进程的判断 #include #include #include #include int main() { pid_t pid; int idx = -1; -
Linux中fork()函数创建进程
2019-05-09 22:05:09Linux系统中学习fork函数创建进程前言一.准备工作二.任务三.感想 前言 最近学习到操作系统原理中的进程同步的知识点时,为了加深对进程的了解,就实践了一下在Linux系统中fork()函数的使用。 一.准备工作 ... -
进程和线程的创建(linux) 源代码
2016-01-02 20:41:47这个程序创建一个子进程,执行an_ch2_1b。这个程序不断地输出如下行: Those output come from child,[系统时间] 观察程序运行的结果,并对你看到的现象进行解释。 2。在linux环境下编写一个控制台应用程序,程序中... -
C语言创建子进程
2020-12-29 20:12:16程序运行的时候,可以创建与自己关联的子进程,创建了这个子进程之后,可以选择等待这个子进程执行完毕,也可以让子进程与自己并行执行,还可以终止自己转而执行子进程。这些操作都是通过一系列相似而又有细微区别的... -
Linux c/c++之进程的创建
2022-03-04 21:10:08待被创建进程执行结束之后当前进程继续执行 #include <stdio.h> #include <unistd.h> #include <stdlib.h> int main(){ printf("先休息再工作\n"); sleep(5); for (int i = 0; i < 5; ++... -
操作系统实验报告_Linux进程创建与通信.doc
2021-05-10 04:20:52操作系统实验报告_Linux进程创建与通信2011-2012学年第一学期专 业:班 级:学 号:姓 名:提交日期:2011年11月实验二 Linux进程创建与进程通信【实验目的1. 熟悉有关Linux系统调用;2. 学习有关Linux的进程创建,... -
实验二 进程创建
2019-11-07 22:00:31实验二进程的创建 一、实验目的 1.加深对进程概念的理解,明确进程和程序的区别。 2.掌握进程的创建方法 二、实验学时 2学时 三、实验内容 1.ps命令的使用(请将使用的命令和结果写在实验报告册中) (1)显示所有... -
Linux使用fork()方法创建进程
2020-05-12 12:41:36在做操作系统的实验过程中,自己安装了Ubuntu(18.04.1)64位,在这里给大家安利一个VX...实验应该是要验证进程之间的并发性,就是输出字符的顺序是不一定的,但是也许是由于代码太简单的缘故,导致输出顺序每次都是固定 -
树莓派创建进程
2017-03-10 17:11:25在 /home/pi/.config 下创建一个文件夹,名称为 autostart,并在该文件夹下创建一个xxx.desktop文件(文件名以.desktop结尾,前面可以自定义),文件内容如下:nano XXX.desktop [Desktop ... -
循环中fork()创建的进程数量
2019-01-14 13:21:42包括初始的父进程,总共下面创建了多少个进程 创建了16个进程,该程序可以加入printf()语句来更好说明创建了几个进程 #include <stdio.h> #include <unistd.h> int main() { int i; ...