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

在fork()之后使用printf并且父级处于等待()状态时出现意外行为

在fork()之后使用printf并且父级处于等待状态时出现意外行为。

在fork()系统调用之后,会创建一个子进程,子进程完全复制了父进程的地址空间,包括打开的文件描述符和其他资源。但是,由于操作系统的调度策略是不确定的,父进程和子进程的执行顺序是无法确定的。这可能导致在父进程调用printf并处于等待状态时,子进程也会打印相同的内容。

这种情况下,可能会出现以下两种意外行为:

  1. 输出混乱:由于父进程和子进程的执行顺序是不确定的,它们可能交错执行,导致输出混乱。例如,父进程和子进程的printf语句交错输出,导致输出的内容无法按照预期的顺序呈现。
  2. 输出重复:父进程和子进程都会执行printf语句,导致输出的内容重复出现。这是因为子进程完全复制了父进程的地址空间,包括已经输出的内容,所以子进程也会再次输出相同的内容。

为了避免这种意外行为,可以采取以下两种方式之一:

  1. 在fork()之前使用printf并调用fflush(stdout):通过在fork()之前使用printf并立即调用fflush(stdout)函数,可以确保父进程的输出被刷新到标准输出缓冲区中。然后,在fork()之后,父进程和子进程都会有各自独立的标准输出缓冲区,避免输出混乱和重复。

示例代码如下:

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

int main() {
    printf("Before fork()\n");
    fflush(stdout);

    pid_t pid = fork();

    if (pid == 0) {
        // 子进程
        printf("Child process: Hello!\n");
    } else if (pid > 0) {
        // 父进程
        printf("Parent process: Hello!\n");
        wait(NULL);
    } else {
        printf("Fork failed!\n");
        return 1;
    }

    return 0;
}

推荐的腾讯云相关产品:腾讯云计算服务

腾讯云计算服务(Tencent Cloud Computing)是腾讯云提供的一整套云计算解决方案。它提供了丰富的云计算产品和服务,包括计算、存储、数据库、安全、网络等,满足不同规模和行业的用户需求。

产品介绍链接地址:腾讯云计算服务

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

相关·内容

【Linux】操作系统与进程

但是要注意,我们查看进程时,不能只根据表面来推测判断它处于什么状态,而应该更严谨的去分析进程的行为再做判定。...这是因为我们在进程中调用了printf()函数,即调用了硬件设备显示器来向屏幕上打印内容,而当硬件显示器在打印内容时,进程就是处于等待硬件工作的状态的, 并且硬件显示器向屏幕打印的时间相对CPU运行时间来说很慢...并且该进程不会响应任何操作系统的请求, 即操作系统无法将其杀死或者是进行其他任何操作。这样做主要是为了防止操作系统将某些重要的正处于等待状态的进程误杀。...当进程退出并且父进程(使用wait()系统调用,后面讲)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程 僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。...我们通过一段代码演示一下僵死状态,我们用fork()创建一个子进程,然后让它休眠3秒之后直接退出,同时我们让父进程休眠30秒,这样在子进程退出后由于父进程处于休眠状态就没法立即回收子进程的信息,子进程就会进入僵死状态

11310

【Linux】进程状态

A:   fork多创建了一个进程, 返回两个值是为了区分不同的执行流,执行不同的代码块; B: 其实fork之后的代码是父子进程共享的,fork函数既然是函数,且有返回值,那么内部一定有return...一般情况下,子进程和父进程也是共享数据的,但是一直共享数据也不现实,因为当我们要修改数据时,会把两个进程的数据都改了,这并不是我们想要的,但是重新开一块空间拷贝父进程的数据又有点浪费,所以linux就使用了一种叫写时拷贝的技术...阻塞:         阻塞可以说是处于一种等待的状态,大多会涉及到外设,外设的速度是毫秒级的,CPU的速          度是纳秒级的,相差6个数量级,所以一般涉及外设的访问,大多数会处在阻塞状态;...        处于阻塞状态的进程会被放到等待队列中,需要注意的是,内存中有非常多的等待队列,而            运行队列只有一个(有几个CPU就有几个运行队列)。...当进程退出并且父进程(使用wait()系统调用)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程;      僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。

23110
  • 【Linux修炼】8.进程概念

    2.6 通过系统调用创建进程-fork初识 1. fork创建子进程 我们通过man fork了解到,fork是创建子进程的函数,但是当这个函数执行前,只有自己本身这个进程和他的父进程,执行之后,这个自己本身的进程就会变成子进程的父进程...即fork()之后,因为pid既可以是0也可以是1,会有父进程+子进程两个进程在执行后续代码(即两条路线去执行if和else if两个分支),fork()的后续代码,被父子进程共享,让父子进程执行后续共享代码的一部分...需要注意的是:我们所提到的这些拖拽,排队,不是进程本身的行为,而是他们PCB的行为! 因此所谓的进程的不同状态,本质就是进程在不同的队列中,等待某种资源!...5. t追踪暂停状态 对于追踪暂停状态,其实是一种特殊的停止状态,即进程在调试时就处于追踪暂停状态:(gdb) 6....暂停、追踪暂停等状态表现出来,而进程处于这些状态时是否会被调整为挂起状态,用户是不可得知的,因为操作系统没必要将挂起状态暴露给用户,用户也不关心一个进程是否会处于挂起状态。

    55600

    【玩转Linux】如何快速理解进程概念

    状态: 任务状态,退出代码,退出信号等。 优先级: 相对于其他进程的优先级。 程序计数器: 程序中即将被执行的下一条指令的地址。...S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠interruptible sleep)。...当进程退出并且父进程(使用wait()系统调用,后面讲)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程 僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。...可父进程如果一直不读取,那子进程就一直处于Z状态?是的!...内存泄漏 进程状态总结 至此,值得关注的进程状态全部讲解完成,下面来认识另一种进程 孤儿进程 父进程如果提前退出,那么子进程后退出,进入Z之后,那该如何处理呢?

    6510

    Linux之进程概念

    我们可以看到,fork之前的代码是父进程自己执行的,之后的代码是父子进程都执行 需要注意的是,虽然父子进程共享代码了,但是其实是各自开辟空间(采用写时拷贝); 小贴士:使用fork函数创建子进程后就有了两个进程...fork返回值: 1.如果fork函数创建子进程成功,那么在父进程中返回父进程的pid,子进程的返回0 2.如果创建失败,那么父进程的返回-1....浅睡眠状态——S 一个进程处于浅睡眠状态,也叫可中断睡眠状态,意味着等待某件事情的完成,处于浅睡眠状态的进程随时可以被唤醒,也可以随时被杀掉 当我们在一个进程中加入sleep(100),意思就是在这里休息一百秒...例如,对于下面的代码,当程序执行五次之后,子进程便会退出,但是父进程不知道它退出了,那么此时子进程就处于僵尸状态。...但是父进程一直在不停的执行,所以子进程就一直处于僵尸状态 僵尸进程的信息会一直存在与task_struct(PCB)中,所以PCB就需要一直去维护 若一个父进程创建了多个子进程,并且不对其进行回收,那么就会造成资源浪费

    11610

    【linux】进程理解

    进程调度信息: 包括进程优先级、进程调度状态(如就绪、运行、等待等),以及其他与调度相关的信息。 处理器时间片(时间片调度情况下)和其他调度参数。...状态切换:在多任务操作系统中,CPU在不同进程之间切换时,需要保存和恢复进程的状态,这由PCB完成。 资源管理:通过PCB,操作系统可以跟踪和管理进程所使用的所有资源,从内存到I/O设备。...在子进程中,fork() 返回 0。 如果出现错误,如内存不足,fork() 只会在父进程中返回一个负值,并且不会创建子进程。...使用 fork() 系统调用来创建子进程,并分别在父子进程中实现了无限循环,打印各自的状态信息。父子进程的行为及如何使用 fork()。...在调用 fork() 时,操作系统会通过复制发出 fork() 调用的进程(父进程)来创建子进程。

    15010

    【Linux】进程控制(创建、终止、等待)

    fork函数的使用,以及写时拷贝机制的原理等,并且也学习了什么是僵尸进程,但是并没有具体讲到应如何处理僵尸进程,本次章节将对fork函数以及如何终止进程,还有僵尸进程的处理做更为详细的探讨。...当调用fork函数之前,父进程独立运行,调用fork之后,会执行两个执行流,即父子进程共享fork函数之后的代码。...,否则就算自己被kill掉了,也是处于一种僵尸状态(Z状态)存在着,直到父进程拿到自己的退出码以及退出状态,子进程才结束僵尸状态(bash的子进程由于bash有回收机制,所以不会出现僵尸进程)。 ​...所谓阻塞式等待,就是父进程运行到waitpid该处的指令时,不会再往后继续执行指令,而是处于阻塞状态,等到子进程退出时,才会继续执行后面的指令。...所谓非阻塞式等待,就是父进程在执行waitpid指令时,假如子进程没有退出,则会给waitpid返回一个0,然后继续执行后面的指令。

    3.5K40

    Linux 进程管理

     3)守护进程:守护进程是一直运行的一种进程,经常在linux系统启动时启动,在系统关闭时终止。它们独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件。...0,并且返回都将执行fork之后的语句。...,而在 之后,父进程和新创建的子进程都在运行,子进程拷贝父进程的代码段,所以子进程中同样有 if(pid<0) printf("error in fork!")...调度程序在进行调度时,首先从处于“内存就绪”或“被抢占”状态的进程中选择一个其优先数最小(优先级最高)的进程。...2、是不是有更高优先级的进程在活动队列中等待调度?如果任何一种情况成立,就把则当前进程的执行状态终止,放到等待队列中,换当前在等待队列中优先级最高的那个进程执行。

    4.2K10

    【Linux系统编程】—— 进程与进程管理在Linux中的基本概念

    子进程通过返回值得知它自己是子进程,并且执行子进程的逻辑。 原因:fork() 的这种行为是为了区分父子进程,便于父进程与子进程执行不同的代码。...这允许父进程可以知道它创建了哪个子进程,并且可以与子进程进行进一步的交互(例如等待子进程结束、获取子进程状态等)。 子进程返回值: 在子进程中,fork() 返回的是 0。...通过将 fork() 的返回值区分为父进程返回子进程的 PID 和子进程返回0,可以让父进程与子进程在代码中做不同的事情。例如: 父进程可以继续执行它的任务或等待子进程结束。...影响父进程的管理 当父进程没有及时回收子进程的状态时,父进程可能无法正常获取子进程的退出码,影响父进程后续的执行逻辑。...使用 signal 处理:父进程可以通过设置信号处理函数来在子进程终止时自动回收其状态。

    10210

    【Linux】进程管理:状态与优先级调度的深度分析

    另外如果计算机只有一个处理器,那么一次最对只有一个进程处于这种状态。 (2)S- -可中断睡眠状态(sleeping) 处在这个状态意味着进程在等待事件完成。.../运行某一个可执行程序,这种是最常见的方式 使用系统调用接口创建进程,即使用fork() 当时用 fork() 函数之后,就在原来的进程中创建了一个子进程,在 fork() 之前的代码只被父进程执行,在...为啥带了printf之后,查出的状态就是S状态?...因为 I/0 速度比较慢因此当它在while中检测该条件,执行printf代码,才能真正叫作运行状态(R状态) 也就是 放到运行队列里,被CPU 所调动时,其状态才叫作R状态,很多时候进程都处于等待状态...当进程退出并且父进程(使用wait()系统调用,后面讲) 没有读取到子进程退出的返回代码时就会产生僵死(尸)进程 僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。

    34010

    【Linux】进程概念(上)

    结合目前,我们得出一个小结论,只有父进程执行 fork() 之前的代码,fork() 之后的代码,父子进程都要执行。 那么我们为什么要使用 fork() 创建子进程呢?...我们首先需要知道,如果一个函数执行到 return,它的核心工作已经完成了,但是 fork() 之后,代码共享,当代码执行到 return 的时候,return 也是代码,是代码就要进行共享,所以当父进程被调度时...这个状态是专门针对磁盘来设计的,而且处于当前进程状态是不可被终止的,操作系统也没有资格!因为访问磁盘的速度很慢,必须要等待磁盘做出响应。...Z(zombie) - 僵尸进程 僵尸状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面讲)没有读取到子进程退出的返回代码时就会产生僵尸进程。...僵尸进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。 所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态。

    12710

    进程控制实验--fork()

    fork( )只是将父进程的用户级上下文拷贝到新进程中,而exec( )系列可以将一个可执行的二进制文件覆盖在新进程的用户级上下文的存储空间上,以更改新进程的用户级上下文。...用fork( )建立子进程,然后在子进程中使用exec( ),这样就实现了父进程与一个与它完全不同子进程的并发执行。...(3)若未找到处于“僵死状态”的子进程,则调用进程便在可被中断的优先级上睡眠,等待其子进程发来软中断信号时被唤醒。...如果调用进程在执行exit( )时,其父进程正在等待它的终止,则父进程可立即得到其返回的整数。...四、分析原因 程 序在调用fork( )建立一个子进程后,马上调用wait( ),使父进程在子进程结束之前,一直处于睡眠状态。

    2.4K80

    了解Linux环境下的进程

    关于放回值 在父进程中,fork会返回新创建子进程的进程ID,在子进程中,fork返回0。如果出现错误,fork会返回一个负值。...也就是说,在fork函数执行完毕后,如果创建进程成功,则出现两个进程,一个子进程,一个父进程。在子进程中,fork函数返回0,在父进程中,fork返回新创建的子进程的进程ID。...(Zombies)是一个比较特殊的状态,当进程退出并且父进程没有读取到子进程退出的返回代码就会产生僵尸进程。...僵尸进程会终止状态保持在进程表中,并且会一直等待父进程读取退出状态代码。 所以,只要子进程退出,父进程还在运行,但是父进程没有读取子进程的状态,子进程进入僵尸状态。...可是父进程如果一直不读取,那子进程就一直处于Z状态。

    10010

    【Linux】开始掌握进程控制吧!

    2 进程创建 2.1 fork函数初识 在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。...父进程与子进程同理,父进程为了便于管理子进程,所以fork函数会返回对应子进程的pid。 2.3 写时拷贝 通过图解可以很好理解写时拷贝。...父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息 也就是说,任何进程在退出时都要被父进程进行等待,不然子进程处于僵尸进程就会造成内存泄漏!!!...,并且会存在一段时间的窗口期,此时子进程处于僵尸进程: 在这个父进程等待的过程中,父进程一直在等待子进程的退出,处于阻塞等待状态。...父进程本质是等待某种软件条件就绪,那么如何理解阻塞等待子进程呢??? 就是把自己列入等待队列,把状态列入不运行状态,等待子进程(类似scanf 的阻塞)。

    10910

    Linux僵尸进程以及wait函数

    僵尸进程产生的原因:每个Linux进程在进程表中都有一个进入点,内核执行该进程时,使用到的一切信息都存入在进程点。我们可以使用ps命令来查看进程状态。...0; } 运行结果如下: 当子进程打印完I am son之后,子进程结束,并且使用了_exit进行了退出。...那么可以使用signal函数为信号SIGCHLD注册处理函数。当子进程结束之后会发出SIGCHLD信号,然后父进程会收到该信号,可以在信号处理函数中使用wait函数来回收子进程。...当他为0时,和wait()一样,阻塞父进程,等待子进程退出。当他取值为WNOHANG时,如果没有已经结束的子进程则马上返回,返回值为0。最常用的就是这两个。...当我们知道系统有僵尸进程出现之后,使用ps aux | grep Z命令来查看处于僵尸状态的进程。 可以看到有一个僵尸进程。

    1.8K10

    进程概念

    -fork初识 运行 man fork 认识fork fork有两个返回值 父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝) fork 之后通常要用 if 进行分流 #include <stdio.h...(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里 S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠) D磁盘休眠状态...当进程退出并且父进程(使用wait()系统调用)没有读取到子进程退出的返回代码时就会产生僵尸进程僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。...,因为他要告诉父进程,你如果父进程如果一直不读取,那子进程就一直处于Z状态。...,也就是子进程先修改,完成之后,父进程再读取 g_val=100; printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val

    56610

    Linux进程——Linux进程与进程优先级

    当进程退出并且父进程(使用wait()系统调用,后面讲) 没有读取到子进程退出的返回代码时就会产生僵死(尸)进程 僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。...1.2 为什么会存在僵尸状态 Linux进程中,当一个进程死亡时不会立刻销毁,而是要等待我们读取死亡信息后才会死亡!...因此我们可以知道:当进程退出但是还没被读取退出信息时处于僵尸状态 PCB释放: 当一个进程在退出的时候,退出信息会由OS写入到当前退出进程的PCB中,可以允许进程的代码和数据空间被释放,但是不能允许进程的...可父进程如果一直不读取,那子进程就一直处于Z状态!...开个玩笑,孤儿进程是父进程在子进程退出之前就先退出了,此时的子进程就称为“孤儿进程” 但是前面刚刚讲过一个进程在死亡时,PCB的死亡信息必须被读取后,才会释放PCB,但是如果父进程已经退出了,子进程的

    11110

    Linux:进程概念(二.查看进程、父进程与子进程、进程状态详解)

    fork 调用成功时,在父进程中返回子进程的 PID,而在子进程中返回 0。 如果 fork 调用失败,则返回一个负数,表示错误。...在 fork 调用后,父子进程都会继续执行 fork 调用之后的指令,但是它们会在不同的地址空间中运行,即它们各自拥有独立的内存空间。...例如处于运行状态的进程会被分配 CPU 时间片并执行指令;处于阻塞状态的进程会被放入阻塞队列中等待某种事件的发生,如 I/O 操作的完成 运行 一个 CPU 一个运行队列: 在操作系统中,为了有效地管理进程的调度和执行...阻塞 当进程需要等待某种事件发生时,例如等待 I/O 操作完成或等待某个信号,它会进入阻塞状态。在阻塞状态下,进程暂时停止执行,让出 CPU 给其他可以执行的进程。...进程进入等待队列确实意味着它被链接到底层设备。这样,当设备就绪并且有了相应的数据或事件时,操作系统可以从等待队列中找到相应的进程,并唤醒它们以继续执行。

    1.8K10

    Linux之进程控制

    此外还可以通过调用fork函数创建子进程,子进程和父进程共享fork之后的代码,可以采用对fork返回值进行判断的办法来让父子进程分别执行后续代码的一部分。...首先来看使用exit时的结果: 再来看看使用_exit时的结果: 可以看到两者之间最大的区别就是exit在程序结束时会将缓冲区内的数据刷新出来,但是_exit却不会将缓冲区刷新出来。...因此可以得到一个结论:缓冲区并不在内核空间当中,而是一个用户级的缓冲区。 三.进程等待 当子进程退出以后,如果父进程一直不回收子进程的资源,那么子进程就会处于僵尸状态,会造成内存泄漏的问题。...在他下楼我们挂掉电话之前我什么也干不了,只能一直保持着和他打电话的状态。 这种舔狗式的等待方式就是阻塞式等待,但是父进程一直保持着等待状态,直到子进程运行完毕父进程再去回收子进程的资源。...4.非阻塞式等待 在非阻塞等待中,父进程会采用轮询的方式检测子进程的状态,如果子进程没有退出,那么父进程就去继续做自己的事,如果在某一次询问中,父进程发现子进程已经结束了,那么父进程就会去回收子进程的资源

    82810

    【Linux 进程状态】—— 从创建到消亡的全生命周期

    我们在Linux系统中使用 man 2 fork 指令可以看到fork系统调用的详细说明。...进程状态 如同人一样,当你在上课时,你的状态是听课中,当你在睡觉时,你的状态时休息中,当你在排队打饭时,你的状态是等待中,当你在打篮球时,你的状态时运动中… 进程也同样如此,有着不同的状态,方便我们对进程更好的管理和操作...这是因为我们的程序中有printf函数,涉及到了IO操作,当程序要进行IO操作时,可能会处于浅度休眠状态,因为要占用硬件资源,向显示器打印,这时有可能其他进程正在使用,所以我们的进程就会进入浅度休眠状态...还有一种情况,当我们的程序中使用sleep函数时,进程也会进入S状态。 例如:我们让它每隔一秒钟打印一次,此时就会处于S状态。...处于僵尸状态的进程已经释放了大部分资源,但仍保留了一些进程控制块信息,等待父进程来回收。

    8910
    领券