首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么在c中使用fork进行两次父打印?

在C语言中使用fork函数进行两次父进程打印的原因是因为fork函数的作用是创建一个新的进程,新进程是原进程的一个副本。在fork函数被调用后,会产生两个进程,一个是父进程,一个是子进程。父进程和子进程几乎完全相同,但是它们有不同的进程ID(PID)。父进程会继续执行fork函数之后的代码,而子进程会从fork函数返回的地方开始执行。

因此,当在父进程中使用fork函数进行两次打印时,会产生两个子进程,每个子进程都会执行一次打印操作。这样就会导致父进程打印两次。

下面是一个示例代码:

代码语言:txt
复制
#include <stdio.h>
#include <unistd.h>

int main() {
    pid_t pid;

    pid = fork();

    if (pid == 0) {
        // 子进程
        printf("This is child process\n");
    } else if (pid > 0) {
        // 父进程
        printf("This is parent process\n");
    } else {
        // fork失败
        printf("Fork failed\n");
    }

    return 0;
}

输出结果为:

代码语言:txt
复制
This is parent process
This is child process

在这个例子中,父进程先执行,然后创建了一个子进程,子进程从fork函数返回的地方开始执行。因此,父进程会打印"This is parent process",子进程会打印"This is child process"。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

【Linux系统编程】通过系统调用获取进程标识符 及 创建子进程(fork)

我们猜想第二个打印应该被执行了两次,因为fork又创建了一个子进程,所以有两个进程,那就有两个执行流去执行第二个打印,所以打印了两次。...,我们来看一下他返回的到底是什么: 翻译一下就是: fork成功的话,在父进程中返回子进程的PID,在子进程中返回0。...失败的话,-1在父进程中返回,不会创建任何子进程,并且正确设置了errno(C语言中一个用于表示错误码的全局变量,Linux内核是C语言写的)。 也就是说fork成功的话,返回值会有两个。...3.5 fork 之后通常要用 if 进行分流 fork 之后通常要用 if 进行分流,这样可以根据需要在父子进程中执行不同的操作。...fork成功之后,父进程和子进程代码共享(我们上面fork之后父子进程都执行了第二个打印就可以证实这一点),通常我们要使用if语句进行代码块分流。

43310

【Linux进程控制】二、进程控制——fork()系统调用深度刨析

fork()最大的特点就是一次调用,两次返回,两次返回主要是区分父子进程,因为fork()之后将出现两个进程,所以有两个返回值,父进程返回子进程ID,子进程返回0。...我们已经知道,fork()系统调用的特点是一次调用两次返回,并且子进程的创建是对父进程的复制,那么是从哪复制开始复制的呢,我们根据程序运行结果分析,程序只打印了一次begin语句,说明不是从头开始复制的...我们看到的运行结果中红色标记的①,实际上是由父进程打印的,②是由子进程打印的,既然不是一个进程打印的,那也就没有先后顺序的问题了。...而子进程打印的父进程ID是1,父进程打印的自己的ID是5270,这是因为在子进程结束前,父进程就已经结束了,新建的子进程变成了孤儿进程,所以它会被1号进程收养,所以新建子进程的父进程ID是1,这也是为什么第二个...3.2 进程顺序控制 使用fork()创建的进程都是一样的,在操作系统看来没有区别,先后顺序也是不确定的,我们要想控制进程的退出顺序,需要自己去实现这个逻辑。

87010
  • linux进程控制

    ; 2.对于fork函数的再谈 2.1调用fork做的事情 分配新的内核段和内核数据结构给子进程,然后给这个子进程拷贝一份父进程的数据,接着把这个子进程添加到我们系统的进程列表里面,最后是使用调度器进行调度...content说明这个父进程和子进程的空间虽然是不一样的,但是这个里面运行的内容是一样的,这个其实就是我们前面说的这个子进程是拷贝的这个父进程; 5.2题目说明 下面两次调用这个fork函数,打印的结果应该是什么...2759,2760说明两次调用的时候都是作为父进程,因为父进程调用fork函数,返回这个子进程的pid,子进程的返回值是0,如果不是0,说明这个是父进程,我们对照发现这个只有A进程两次调用的时候都是作为父进程的...,虽然这个进程C没有参与这个第一次调用,但是这个C的父进程是A,这个A第一次是作为父进程的,我们的这个C进程实际上是拷贝的这个父进程的数据,因此这个打印的结果是2759,其实也就是进程A第一次的pid数值...; 同理,我们就可以进行这个第四个输出结果的分析了,这个打印结果是两个0,实际上这个两次作为子进程的进程应该也是不存在的,但是这个D第二次作为子进程打印0,第一次实际上就是因为拷贝的是自己的父进程B的代码和数据

    5410

    【linux】进程理解

    继承父进程的环境设置和任何其它相关的上下文信息。 返回值 fork() 函数调用后会有两次返回: 在父进程中,fork() 返回新创建的子进程的进程 ID。 在子进程中,fork() 返回 0。...返回值 上面提到fork() 函数调用后会有两次返回: 在父进程中,fork() 返回新创建的子进程的进程 ID。...使用 fork() 系统调用来创建子进程,并分别在父子进程中实现了无限循环,打印各自的状态信息。父子进程的行为及如何使用 fork()。...这里和后面要学的虚拟地址空间和父子写实拷贝有关系 fork函数为什么会返回两次? fork() 函数之所以会返回两次,是因为它在被调用时负责创建一个新的进程(子进程)。...这一过程生成了两个几乎完全相同的进程:原有的父进程和新创建的子进程,从而使得 fork() 看似返回了两次,但实际上是在两个不同的进程中返回: 在父进程中返回:对于父进程,fork() 返回新创建的子进程的进程

    15010

    【Linux】理解缓冲区

    为什么呢?肯定和fork有关! C接口的函数被打印了两次系统接口前后只是打印了一次:和fork函数有关,fork会创建子进程。...3.在哪里 缓冲区的位置究竟在哪里:从上面的例子我们直接往显示器上打印结果为4条,往文件打印为7条,这跟缓冲区有关,同时这也说明了缓冲区一定不在内核中,为什么?...如果在内核中write也应该打印两次,write是系统接口。我们之前谈论的所有缓冲区都指的是用户级语言层面提供的缓冲区。...现在,我们现在重新来看一看刚开始的现象: 1.如果我们没有进行重定向>,看到了4条消息,stdout默认使用的是行刷新,在进程fork之前,三条C函数已经将数据打印输出到显示器上(外设),你的FILE...在执行fork的时候,stdout属于父进程,fork创建子进程紧接着就是进程退出,谁先退出就要进行缓冲区刷新,刷新的本质就是修改,修改的时候发生写时拷贝!所以数据最终会显示两份!

    25840

    linux中fork()函数详解(原创!!实例讲解)

    fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:     1)在父进程中,fork返回新创建子进程的进程ID;     2)在子进程中,fork返回0;    ...在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。...引用一位网友的话来解释fpid的值为什么在父子进程中不同。...函数在子进程中返回0),代码内容为: [c-sharp] view plaincopy for(i=0;i<2;i++){       pid_t fpid=fork();//执行完毕,i=0...我们再来仔细分析一下,为什么是还有19个进程。     第一个fork和最后一个fork肯定是会执行的。     主要在中间3个fork上,可以画一个图进行描述。

    4.1K30

    Linux系统编程:理解进程进程管理

    ----管理一个对象我们还是遵循以往的套路:先组织,再描述; 二,简单理解进程管理 2.1描述进程 我们写好的C/C++程序保存在磁盘上,当我们要使用的时候,OS会将此程序的代码和数据加载到内存中,而这个时候其实就可以叫做是一个进程块了...其中以数字命名的文件夹就是对应进程的PID,里面包含进程的各种信息; 1.其中cwd是当前进程的工作目录,所以为什么我们使用文件的相对路径为什么是莫问当前路径的,还有C程序中fopen的文件是当前目录下的...; 6.2fork的返回值分析 fork为什么给子进程返回0,其实对于子进程来说只是一个标识作用,他可以使用ps 查看自己的PID和父进程的PID; fork为什么给父进程返回子进程的PID;因为父进程需要对创建的子进程进行管理...6.6fork语句之前的语句是否还会执行? 答案是不会,但是会发生拷贝到子进程中! 按照推测"执行此处"只会打印一次 为什么出现了两次"执行此处"呢?...,因此出现了两次"执行此处",并不是子进程执行了printf语句; 下面我们加上\n 父进程会自动把"执行此处"从缓冲区中刷新,而子进程是不会执行fork之前的语句的,所以只打印了一次"执行此处"!

    5100

    【Linux】进程与可执行程序的关系&&fork创建子进程&&写实拷贝的理解

    之后,为父子进程共享,所以第二条printf语句会打印两次。...我们也可以看到,其中父子进程fork的返回值是不一样的,父进程fork返回的是子进程的pid,子进程返回的是0。 那这里就会有疑问了,为什么fork给父进程返回子进程的pid,给子进程返回0?...原因是在进程中,一个父进程可能会有多个子进程,父进程想要管理子进程必须通过子进程的标识符,所以父进程必须知道子进程的标识符,而子进程只需要关心自己是否成功创建了,所以返回0。...那fork函数为什么会返回两次呢?...进程都有自己的代码和数据,系统创建出来的子进程的PCB默认就会指向父进程的代码和数据,想让父子进程分别执行不同的程序,那就可以在代码中根据父子进程fork返回值的不同设置ifelse语句,让父子进程分别执行不同的代码

    19610

    fork函数简介_fork()&&fork()

    fork()子进程与父进程之间的文件描述符问题 在C程序中,文件由文件指针或者文件描述符表示。...文件描述符表:用户区的一部分,除非通过使用文件描述符的函数,否则程序无法对其进行访问。对进程中每个打开的文件,文件描述符表都包含一个条目。 系统文件表:为系统中所有的进程共享。...fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:   1)在父进程中,fork返回新创建子进程的进程ID;   2)在子进程中,fork返回0;   3)如果出现错误...在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。   ...引用一位网友的话来解释fpid的值为什么在父子进程中不同。

    1.2K21

    【Linux进程控制】三、进程间的资源共享问题

    \n"); return 0; } 运行后发现打印了两次begin,而根据前面的学习,实际上应该打印一次才对 实际上这是printf()函数缓冲区的机制造成的,缓冲区我们在Linux系统调用专题中已经讲过了...在系统调用时,遇到 '/n' 输出行缓冲,我们这里第一个printf()函数中没有 '\n' 字符,所以第一个printf()函数执行的时候没有打印缓冲区的内容,当我们fork一个子进程的时候,我们既没有输出这个缓冲区的内容...,也没有刷新缓冲区,所以这段内容恢复至到子进程中。...这也是为什么fork在第一个printf()语句之后,子进程却能打印出一个printf()语句中内容的原因,因为缓冲区没有刷新,所以被赋值给了子进程。...、父进程ID、fork()函数返回值、进程运行时间(父进程在fork之前就已经运行了,而子进程在fork之后才开始运行)、定时器、未决信号集等不同。

    12210

    初识Linux下进程

    其实就是在cwd路径下创建,当系统在执行C语言代码时,执行到当前这行就会拿到进程的cwd。...上运行起来可以观察到:   运行起来之后,我们发现,fork之前的打印只执行了一次,而fork之后的打印却执行了两次,多次运行都是这个结果,说明并不是偶然现象。   ...进程也是如此,因为子进程有多个,要想父进程准确无误的找到子进程就需要子进程的pid,而子进程只有一个父亲,并不需要返回特殊值。 为什么fork会返回两次呢?   ...那么我们再考虑那个问题,fork为什么既可以是0又可以是别的数,fork在返回时返回的操作,就是在对变量进行写入,所以子进程会发生写时拷贝。   ...运行起来的程序是 通过进程属性信息中的 cwd 来获取路径信息 的。   创建子进程需要使用 fork函数接口,子进程会 继承父进程的部分属性字段,并且和父进程 共享代码段。

    8510

    【Linux探索学习】第十二弹——初识进程:进程的定义、描述和一些简单的相关操作

    需要注意的一点是进程的程序是一定被加载在内存中的,因为进程是系统将要进行处理的数据,而CPU是从内存中获取数据的,所以说进程的程序一定被加载在内存中的,比如我们vim写的一个.c的C语言程序,它在操作系统下的本质就是一个文件...,而ppid一直不变,也就是说子进程编号一直在变化,而父进程一直没变,为什么会出现这个现象呢?...return 0; } 运行结果: 我们注意到在fork()函数之后的第二行打印语句执行了两次,说明在fork()之后一个进程变成了两个进程 此外,fork函数还有一个重要知识就是它是有两个整形返回值的...比如fork为什么要给子进程返回0,给父进程返回子进程pid呢?...其实这就是为了区分父子进程,让不同的执行流执行不同的代码 一般而言fork之后的代码是共享的,这也就是为什么上面的 "hello linux" 打印了两遍的原因,因为父子进程都执行了它,那么如果此时子进程对共享数据进行操作了

    14110

    【Linux修炼】13.缓冲区

    C接口打印两次的现象 二. 理解缓冲区问题 为什么要有缓冲区 缓冲区刷新策略的问题 所说的缓冲区在哪里?指的是什么缓冲区? 三. 解释打印两次的现象 四. 模拟实现 五. 缓冲区与OS的关系 一....直接运行仍是正常的现象,但当重定向到log.txt中,C接口的打印了两次,这是什么原因呢?...文章开始时我们提到了C语言接口打印两次的现象,毫无疑问,我们能够从中获得以下信息: 这种现象一定和缓冲区有关 缓冲区一定不在内核中(如果在内核中,write也应该打印两次) 因此我们之前谈论的所有的缓冲区...解释打印两次的现象 有了缓冲区的理解,现在就足以解释打印两次的现象: 由于代码结束之前,进行创建子进程: 如果我们不进行重定向,看到四条消息 stdout默认使用的是行刷新,在进程进行fork之前,...数据并没有被刷新,而在fork的时候,stdout属于父进程,创建子进程时,紧接着就是进程退出!

    1.9K00

    Linux系统 —— 进程系列 - 进程的概念,PCB与PID和fork

    - getppid 对上面的概念进行试验之后, 我们再来看一下父进程, 也就是PPID 我们发现,父进程ppid都是不改变的,而pid每次都是变化的,这是为什么呢?...并且没有子进程被创建 也就是说, fork有两个返回值, 并且这两个返回值的类型都是pid_t, 也就是有符号整形 运行结果: 我们可以看到每一秒打印一条父进程, 打印一条子进程...,这说明父进程和子进程是同时进行的,并且id > 0, 和 id == 0同时成立, 如果在其他的代码中, 这两种情况不可能同时存在,但是在调用的fork下就可以 所以在我们fork之后所有的代码都是共享的...pid来区分不同的子进程,而子进程不需要获得父进程的pid,因为子进程已经能够获得getppid了,所以子进程只需要表明自己成功建立就可以了 4.2 fork函数为什么会返回两次?...其实就是由两个执行流会执行它,因为return也是语句,所以会被执行两次,而这两个执行流都会返回一个值,所以这就是为什么fork会有两个返回值, 并且返回值给一个给子进程, 一个给父进程的原因 总结

    12510

    【C++】继承 ⑥ ( 继承中的构造函数和析构函数 | 类型兼容性原则 | 父类指针 指向 子类对象 | 使用 子类对象 为 父类对象 进行初始化 )

    " 应用场景 : 直接使用 : 使用 子类对象 作为 父类对象 使用 ; 赋值 : 将 子类对象 赋值给 父类对象 ; 初始化 : 使用 子类对象 为 父类对象 初始化 ; 指针 : 父类指针 指向...子类对象 , 父类指针 值为 子类对象 在 堆内存 的地址 , 也就是 将 子类对象 地址 赋值给 父类类型指针 ; 引用 : 父类引用 引用 子类对象 , 将 子类对象 赋值给 父类类型的引用 ; 二...); } 2、使用 子类对象 为 父类对象 进行初始化 定义父类对象 , 可以直接使用 子类对象 进行初始化操作 ; // II....类型兼容性原则 : 使用 子类对象 为 父类对象 进行初始化 Parent parent = child; 3、完整代码示例 #include "iostream" using namespace...类型兼容性原则 : 使用 子类对象 为 父类对象 进行初始化 Parent parent3 = child; // 控制台暂停 , 按任意键继续向后执行 system(

    31020

    Linux实验四:进程控制

    要求父进程先以阻塞方式等待子进程结束,当该子进程正常退出后,父进程再创建新的子进程,反复打印“child2 process is active!”;此时结束父进程,并观察子进程的运行情况。...(1)创建子进程1: status =fork();:调用fork函数创建一个新的进程。如果成功,fork返回两次:在父进程中返回新子进程的进程ID,在子进程中返回0;如果失败,返回-1。...如果execl执行失败,使用perror打印错误信息,并调用exit退出子进程1。 (3)等待子进程1完成: 在父进程中,使用wait函数等待子进程1的完成。...(5)子进程2执行循环任务: 在子进程2中,使用无限循环打印信息,并使用sleep函数暂停5秒。 (6)父进程处理: 在父进程中,调用exit函数退出程序。 步骤2....在这个实验中,我学会了如何使用fork()系统调用来创建子进程,并了解了子进程与父进程之间的关系。我还学会了如何使用exec()系统调用来在新的进程中执行程序。

    7100

    【Linux操作系统】计算机体系结构和操作系统与进程概念深入理解

    所以我们还需要再提供一层封装:(用户可能使用下列的一种或多种方式) 用户通过指令操作,在shell上执行命令行操作 用户通过编程操作,调用C/C++库 用户通过点击鼠标,完成窗口操作 再次理解我们printf...所谓对进程的管理,变成了对进程对应的PCB进行管理,对进程对应的链表进行增删查改。 3.查看进程 a. mypro.c: b. makefile: c. make编译后,....杀掉进程=>文件不存在 招式3:gettpid查看父进程的ID a. 在原来mypro.c的基础上稍作修改: printf("I am a process!...pid:%d,getppid:%d\n",getpid(),getppid()); b.make后两次运行: 分析: 为什么PID变化,PPID并没有变化?...返回值 fork调用成功,子进程的ID将返回给父进程,0将返回给子进程 fork调用失败,-1将返回给父进程,没有子进程被创建,错误码将被设置 也就是fork如果调用成功,将有两个返回值

    41220

    如何创建多进程程序?(文末福利)

    来源:公众号【编程珠玑】 作者:守望先生 网站:https://www.yanbinghu.com 前言 在《对进程和线程的一些总结》已经介绍了进程和线程的区别,但是在C/C++中如何创建进程呢?...什么时候需要fork进程 一种可能见到的场景是在服务器程序中,一个请求到来后,为了避免服务器阻塞,fork出一个子进程处理请求,父进程仍然继续等待请求到来。但这种方式无疑开销会稍大。...fork函数原型如下: #include pid_t fork(void); 如果调用成功,它将返回两次,子进程返回值是0;父进程返回的是非0正值,表示子进程的进程id;如果调用失败将返回...test.txt 为什么这里要特别说明打开的文件描述符呢?...本文总结点如下: fork调用一次,返回两次 一个进程可以有多个子进程,但同一时刻最多只有一个父进程 子进程继承了父进程很多属性 父子进程执行的先后顺序不一定 本文仅仅简单介绍了fork,实际上得到子进程之后

    1.7K20

    【Linux】操作系统与进程

    这是因为我们在调用fork()函数之前程序只有一个执行流,而调用fork()函数之后程序就开始有两个执行流了,所以两个执行流都执行了打印操作,我们的屏幕上才会看到两个打印的结果。 ️...,这个测试中fork()函数应该是优先执行父进程的,所以父进程的信息先被打印了出来。...至此,我们发现fork()函数确实是创建了一个新的进程, 只有两个进程一起运行, 这段代码才可能打印出两个if语句的分支循环结果,否则按照C语言单进程的执行逻辑, 程序一旦进入其中一个死循环就再也不可能出来了...进一步探究fork()函数 关于fork()函数,有几个问题需要解答一下: 1.为什么fork()函数要给子进程返回0,给父进程返回子进程pid?...当进程退出并且父进程(使用wait()系统调用,后面讲)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程 僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。

    11410

    fork函数

    子进程使用相同的pc(程序计数器),相同的CPU寄存器,在父进程中使用的相同打开文件。 它不需要参数并返回一个整数值。下面是fork()返回的不同值。 负值:创建子进程失败。...由fork创建的新进程被称为子进程。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。 子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。...所以在移植代码的时候我们不应该对此作出任何的假设。 为什么fork会返回两次? 由于在复制时复制了父进程的堆栈段,所以两个进程都停留在fork函数中,等待返回。...因此fork函数会返回两次,一次是在父进程中返回,另一次是在子进程中返回,这两次的返回值是不一样的。 ? 在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。...fork函数的特点概括起来就是“调用一次,返回两次”,在父进程中调用一次,在父进程和子进程中各返回一次。 fork的另一个特性是所有由父进程打开的描述符都被复制到子进程中。

    1.7K20
    领券