fork的相关问题

缓冲分为:无缓冲(直接输出)  行缓冲(遇‘\n‘输出或fflush)   全缓冲(fflush)

下面的程序一共输出多少个“-”?()

#include <stdio.h>  
#include <sys/types.h>  
#include <unistd.h>  
   
int main(void)  
{  
   inti;  
   for(i=0; i<2; i++){  
      fork();  
      printf("-");  
   }  
   
   return 0;  
}

A.2 B.4 C.6 D.8

如果你对fork()的机制比较熟悉的话,这个题并不难,输出应该是6个“-”,但是,实际上这个程序会很tricky地输出8个“-”。

要讲清这个题,我们首先需要知道fork()系统调用的特性,

  • fork()系统调用是Unix下以自身进程创建子进程的系统调用,一次调用,两次返回,如果返回是0,则是子进程,如果返回值>0,则是父进程(返回值是子进程的pid),这是众为周知的。
  • 还有一个很重要的东西是,在fork()的调用处,整个父进程空间会原模原样地复制到子进程中,包括指令,变量值,程序调用栈,环境变量,缓冲区,等等。

所以,上面的那个程序为什么会输入8个“-”,这是因为printf(“-”);语句有buffer,所以,对于上述程序,printf(“-”);把“-”放到了缓存中,并没有真正的输出,在fork的时候,缓存被复制到了子进程空间,所以,就多了两个,就成了8个,而不是6个。

#include <stdio.h>  
#include <sys/types.h>  
#include <unistd.h>  
   
int main(void)  
{  
   inti;  
   for(i=0; i<2; i++){  
      fork();  
      printf("-\n");  
   }  
   
   return 0;  
}

A.2 B.4 C.6 D.8

Unix下的设备有“块设备”和“字符设备”的概念,所谓块设备,就是以一块一块的数据存取的设备,字符设备是一次存取一个字符的设备。磁盘、内存都是块设备,字符设备如键盘和串口。块设备一般都有缓存,而字符设备一般都没有缓存。

对于上面的问题,我们如果修改一下上面的printf的那条语句为:

printf("-\n");

或是

printf("-");
fflush(stdout);

就没有问题了(就是6个“-”了),因为程序遇到“\n”,或是EOF,或是缓中区满,或是文件描述符关闭,或是主动flush,或是程序退出,就会把数据刷出缓冲区。需要注意的是,标准输出是行缓冲,所以遇到“\n”的时候会刷出缓冲区,但对于磁盘这个块设备来说,“\n”并不会引起缓冲区刷出的动作,那是全缓冲,你可以使用setvbuf来设置缓冲区大小,或是用fflush刷缓存。

#include <stdio.h>  
#include <sys/types.h>  
#include <unistd.h>  
intmain(void)  
{  
   inti;  
   for(i=0; i<2; i++){  
      fork();  
      //注意:下面的printf有“\n”  
      printf("ppid=%d, pid=%d, i=%d \n", getppid(), getpid(), i);  
   }  
   sleep(10);//让进程停留十秒,这样我们可以用pstree查看一下进程树  
   return0;  
}

输出结果为:

ppid=8858,
pid=8518, i=0

ppid=8858,
pid=8518, i=1

ppid=8518,
pid=8519, i=0

ppid=8518,
pid=8519, i=1

ppid=8518,
pid=8520, i=1

ppid=8519,

pid=8521, i=1


时间: 2024-12-15 01:51:53

fork的相关问题的相关文章

boost::asio::io_service(之一)

boost::asio::io_service /// Provides core I/O functionality. /** * The io_service class provides the core I/O functionality for users of the * asynchronous I/O objects, including: * io_service类为下面的异步对象提供了核心的I/O操作函数 * * @li boost::asio::ip::tcp::socke

外部程序(可执行文件)调用的一些问题

第一个问题:c/c++中调用外部程序 在写程序的时候难免会遇到需要调用外部程序或别人写好的可执行文件,当编程工具为c/c++时,通过使用system()函数,或exec家族函数可实现对外部可执行文件的调用.如果使用execlp()函数,会出现一个问题,那便是当execlp()函数调用结束时,后面的代码也不再执行.该问题可通过fork函数创建子进程解决 .而且system()函数本身就是通过fork子进程的方式实现对外部程序的调用. 第二个问题:计算所调用程序的运行时间 为了测试该外部程序对不同数

UNIX网络编程笔记(3)—基本TCP套接字编程

基本TCP套接字编程 主要介绍一个完整的TCP客户/服务器程序需要的基本套接字函数. 1.概述 在整个TCP客户/服务程序中,用到的函数就那么几个,其整体框图如下: 2.socket函数 为了执行网络I/O,一个进程必须要做的事情就是调用socket函数.其函数声明如下: #include <sys/socket.h> int socket(int family ,int type, int protocol); 其中: family:指定协议族 type:指定套接字类型 protocol:指

process credentials(三)

主要内容包括: 1.进程描述符中Realtime Mutex相关数据结构的初始化 2.子进程如何复制父进程的credentials 3.per-task delay accounting的处理 4.子进程如何复制父进程的flag 七.初始化Realtime Mutex相关的成员 static void rt_mutex_init_task(struct task_struct *p) {     raw_spin_lock_init(&p->pi_lock); #ifdef CONFIG_R

AbstractExecutorService的submit方法概要介绍

1.概述 ExecutorService是JDK提供的框架,它简化了异步模式下的任务执行.一般来说,ExecutorService会自动提供一个线程池和API,用于为其分配任务. 2.实例化ExecutorService 2.1 Executors类的工厂方法 打造ExecutorService最简单的方法是使用的的工厂方法之一Executors类. 例如,以下代码行将创建一个包含10个线程的线程池: ExecutorService executor = Executors.newFixedTh

fork()相关的源码解析

fork()的真正执行采用的是do_fork()函数,所以下文将从do_fork()函数对fork()进行源码解析.下图是do_fork()的源码函数设计: 从上图我们可以看到do_fork()涉及到众多的参数.所以在进入do_fork函数进行分析之前,很有必要了解一下它的参数. clone_flags:克隆标识: * * cloning flags: */#define CSIGNAL 0x000000ff /* signal mask to be sent at exit *//** * 共

Linux中相关知识(atexit(),fork(),粘滞位)

1.atexit()函数 函数名: atexit 头文件:#include<stdlib.h> 功 能: 注册终止函数(即main执行结束后调用的函数) 用 法: int atexit(void (*func)(void)); 注意:一个进程可以登记32个函数,这些函数由exit自动调用,这些函数被称为终止处理函数,atexit函数可以登记这些函数. exit调用终止处理函数的顺序和atexit登记的顺序相反,如果一个函数被多次登记,也会被多次调用. 程序例: #include <std

fork炸弹

:(){ :|:& };:                         # 著名的 fork炸弹,系统执行海量的进程,直到系统僵死 fork炸弹(fork bomb)在计算机领域中是一种利用系统调用fork(或其他等效的方式)进行的拒绝服务攻击.与病毒与蠕虫不同的是,fork炸弹没有传染性,而且fork炸弹会使对同时执行进程/程序数设限的系统无法执行新程序,对于不设限的系统则使之停止响应.以fork炸弹为代表的自我复制程序有时亦被称为wabbit. fork炸弹的概念:进程递归式派生(for

Linux Fork Bomb

众所周知,bash是一款极其强大的shell,提供了强大的交互与编程功能.这样的一款shell中自然不会缺少"函数"这个元素来帮助程序进行 模块化的高效开发与管理.于是产生了由于其特殊的特性,bash拥有了fork炸弹.Jaromil在2002年设计了最为精简的一个fork炸弹的实 现. 所谓fork炸弹是一种恶意程序,它的内部是一个不断在fork进程的无限循环,fork炸弹并不需要有特别的权限即可对系统造成破坏.fork炸 弹实质是一个简单的递归程序.由于程序是递归的,如果没有任何限