父子进程

fork 后子进程对父进程的继承

(1)为什么需要创建子进程?

每一个程序的运行都需要进程,创建子进程可以实现宏观上的并行

(2)什么时候需要创建子进程?

当父进程执行到某个阶段,或接收到某个事件后,需要创建一个独立的进程来协助其完成任务时,才需要调用fork创建一个新进程

(3)子进程对父进程的继承

 1.为什么要继承父进程的相关资源,参考  http://blog.csdn.net/xlsernt_sina_com/article/details/31350829

  摘选了两句话:

    父进程创建子进程是为了其能够协助父进程完成某些操作,因此,父进程必须将其自己的一些资源分享给子进程,以便父子进程共同完成任务

    子进程的创建是为了协助父进程完成相关任务,与此目的不相关的资源,子进程没有必要继承,继承了自会白白浪费内存资源

 2.继承的资源,  参考 http://blog.chinaunix.net/uid-24517549-id-4117366.html

  • 用户号UIDs和用户组号GIDs
  • 环境变量
  • 堆栈
  • 共享内存
  • 打开文件的描述符
  • 执行时关闭(Close-on-exec)标志
  • 信号(Signal)控制设定
  • nice值,该值表示进程的优先级, 数值越小,优先级越高
  • 进程调度类别(scheduler class)
  • 进程组号
  • 对话期ID(Session ID) (指:进程所属的对话期 (session)ID, 一个对话期包括一个或多个进程组, 更详细说明参见《高级编程》 9.5节
  • 当前工作目录
  • 根目录
  • 文件方式创建屏蔽字
  • 资源限制
  • 控制终端

3.不继承的资源

  • 进程号PID
  • 不同的进程号(译者注: 即进程进程号与进程进程号不同, 进程号可由getppid函数得到)
  • 子进程自己的文件描述符和目录流的拷贝
  • 异步输入和输出
  • 文件锁,pending alarms和pending signals
  • timer_create函数创建的计时器
  • 阻塞信号集初始化为空集
  • 资源使用(resource utilizations)设定为0
  • 在tms结构中的系统时间
  • 进程继承进程进程正文(text), 数据和其它锁定内存(memory locks) (译者注:锁定内存指被锁定的虚拟内存页,锁定后, 不允许内核将其在必要时换出(page out), 详细说明参见《The GNU C Library Reference Manual》 2.2版, 1999, 3.4.2节)

 4.其他需要注意的

  1.父进程和子进程拥有独立的地址空间和PID参数

  2.经过fork()以后,父进程和子进程拥有相同内容的代码段、数据段和用户堆栈(共享内存)

  3.就像父进程把自己克隆了一遍。事实上,父进程只复制了自己的PCB块。而代码段,数据段和用户堆栈内存空间并没有复制一份,而是与子进程共享。只有当子进程在运行中出现写操作时,才会产生中断,并为子进程分配内存空间。由于父进程的PCB和子进程的一样,所以在PCB中断中所记录的父进程占有的资源,也是与子进程共享使用的。这里的“共享”一词意味着“竞争”

(4)fork的返回值

     fork函数调用一次会返回2次,首先返回pid = 0,返回值等于0的就是子进程;再返回pid 大于0,返回值大于0的是父进程,且这个返回值就是本次 fork创建的子进程ID

(5)父进程对子进程的回收

1.孤儿进程:父进程先结束的时候,系统会把init进程(进程1)变为子进程的父进程

  2.僵尸进程:子进程先于父进程结束,父进程还未来得及将其收尸(系统只是回收了这个进程工作时消耗的内存和IO,而并没有回收这个进程本身占用的内存,8KB,主要是task_struct和栈内存))

  3.回收函数

    wait:阻塞,子进程结束时,系统向其父进程发送SIGCHILD信号   pid_t wait(int *status);

            参考 http://blog.csdn.net/qq_18973645/article/details/52648812

    waitpid:可以回收指定PID的子进程,可以阻塞式或非阻塞式两种工作模式

         pid_t  waitpid(pid, &status, 0);    //0默认表示阻塞

         pid_t   waitpid(pid,&status,WNOHANG)   //表示非阻塞

  

时间: 2024-12-15 20:27:28

父子进程的相关文章

LINUX实现父子进程轮流修改文件的值

本例子是基于信号的同步机制实现父子进程轮流修改文件中的值. tatic volatile sig_atomic_t sigflag; static sigset_t newmask,oldmask,zeromask; static void sig_usr(int signo) { sigflag=1; } void TELL_WAIT(void) { if(signal(SIGUSR1,sig_usr)==SIG_ERR) perror("signal error"); if(sig

父子进程捕捉信号的特点

经过实验:除了2个无法捕捉的信号 只要父进程没有定义该信号,捕捉到信号后,父子都按默认方式处理 父进程定义了,子进程没定义,则父进程按照定义的方式处理,子进程按照默认方式处理: 父子进程都定义,捕捉到后按各自的方式处理.

谈父子进程执行过程

fork函数用于从已存在进程中创建一个新进程,新进程成为子进程,原进程成为父进程.这两个进程分别返回他们各自的返回值, 其中父进程的返回值是子进程的进程号,子进程则返回0,因此返回值大于0标识父进程,等于0标识子进程.所以我们可以通过返回值 来判定该进程是父进程还是子进程.fork函数创建新进程后的父子进程模型如下: 下面用一个简单程序来观察父子进程之间的运行过程: 该代码运行结果如下: 由上述程序可以将父子进程的执行看做如下过程:

父子进程关系

1)父进程先于子进程终止: 此种情况就是我们前面所用的孤儿进程.当父进程先退出时,系统会让init进程接管子进程 . 2)子进程先于父进程终止,而父进程又没有调用wait或waitpid函数 此种情况子进程进入僵死状态,并且会一直保持下去直到系统重启.子进程处于僵死状态时,内核只保存进程的一些必要信息以备父进程所需.此时子进程始终占有着资源,同时也减少了系统可以创建的最大进程数. 僵死状态:一个已经终止.但是其父进程尚未对其进行善后处理(获取终止子进程的有关信息,释放它仍占有的资源)的进程被称为

0707 父子进程之间传递文件描述符

1 /************************************************************************* 2 > File Name: pass_fd.c 3 > Author:Monica 4 > Mail:[email protected] 5 > Created Time: Mon 07 Jul 2014 09:52:49 PM CST 6 ********************************************

堆栈和父子进程的概念

栈帧:堆栈是C语言程序运行时必须的一个记录调用路径和参数的空间 函数调用框架.传递参数.保存返回地址.提供局部变量空间. 堆和栈的关系: 堆栈一般指的是栈:实际上堆和栈是不同的. 堆需要用户在程序中显性申请,空间由用户维护,释放空间不当会导致内存泄漏:但是栈不用,由系统自动完成. 堆的空间比较大,栈比较小. 栈的生命周期短,随着函数退出和返回消亡:堆的生命周期可以是整个程序执行完成退出,但是一般用户都会在使用时申请空间,不用时释放空间,防止空间消耗完毕. 在fork之后处理的文件描述符有两种常见

父子进程通过mmap进行通信

本来打算使用pipe进行父子进程之间的数据交互(应用场景是父进程向多个子进程分发数据,子进程进行处理):但是担心pipe的性能,转而使用mmap实现. 废话少叙,上代码. #include <stdio.h> #include <sys/types.h> #include <signal.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <

fork()函数 —— 父子进程资源问

fork()函数功能--创建新进程 1.父子进程有独立的数据段.堆.栈,共享代码段 Linux中每个进程都有4G的虚拟地址空间(独立的3G用户空间和共享的1G内核空间),fork()创建的子进程也不例外.子进程资源的由来: 1.1G内核空间既然是所有进程共享,因此fork()创建的子进程自然也将拥有: 2.3G的用户空间是从父进程进程而来. fork()创建子进程时继承了父进程的数据段.代码段.栈段.堆,注意从父进程继承来的是虚拟地址空间,同时也复制了页表(没有复制物理块).因此,此时父子进程拥

(待续)进程控制(四)---父子进程之间的复制

用户缓冲区: 由 fork函数创建的子进程会继承父进程的用户缓冲区.如果在父进程调用 fork 函数创建子进程之前缓冲区中仍然有数据在其中的话,那么子进程将会复制父进程的缓冲区. 文件共享: 由 fork 函数创建的子进程会继承父进程打开的所有文件描述符,而且父子进程相同的文件描述符是指向同一个文件表项(共享一个读写偏移指针).IPC(进程间通信)中的 无名管道 就是利用子进程会继承父进程的文件描述符这一特点来实现的.