fork函数

    xiaoxiao2021-03-25  74

    系统环境:ubuntu

    进程特性:

    每一个进程都有一个非负整型的唯一的进程id.一个进程结束之后,其进程id 不用被新创建进程立即复用,大部分unix系统为采用延迟复用算法。

    UNIX 中提供获取进程id 和 父进程 id 函数

    pid_t getpid (void); // return process id pid_t getppid (void); // return parent process id

    fork函数

    pid_t fork(void);

    描述

    通过复制(duplicate)当前进程创建一个新的进程。子进程同时复制了父进程的数据空间、堆。这样父进程和子进程管理各自的存储空间,并不会共享。

    程序在执行fork()之后,子进程和父进程继续执行fork()之后的代码。

    返回值

    true,返回父进程创建的子进程id,子进程返回0;< 0 ,创建进程错误。

    eg:

    在这sleep(1000) 主要为了便于使用 ps -axf 命令 查看进程之间关系。

    执行结果:

    左面程序执行结果,右边ps 进程关系图。看出 父进程3241 子进程 3242 ,子进程id生成遵循延迟算法。 有没有想过为啥只有父进程输出了一个Begin ?

    那么我稍微修改一下代码如下:

    将标准输出改为文件输出,结果如下:

    出现了两次Begin ! 为啥呢?

    还记着缓冲机制吗?上面这个例子明显是全缓冲,全缓冲只有缓冲区已经满了,或者强制刷新才会输出。缓冲之间差异可参考博客:

    http://blog.csdn.net/wning1/article/details/60476480

    解决方法:

    只需要在第一个Begin 输出语句紧接着加上一句fflush(null)。

    下面用一个例子说明僵尸进程

    僵尸进程: 在UNIX 系统中,一个进程结束了,但是他的父进程没有等待(调用wait / waitpid)他, 那么他将变成一个僵尸进程。 但是如果该进程的父进程已经先结束了,那么该进程就不会变成僵尸进程, 因为每个进程结束的时候,系统都会扫描当前系统中所运行的所有进程, 看有没有哪个进程是刚刚结束的这个进程的子进程,如果是的话,就由Init 来接管他,成为他的父进程……

    30000000-30000200 之间寻找素数。

    结果如下:

    子进程运行完毕变为(Z+),父进程还未运行完毕也没有调用wait()函数,子进程就会在创建它的父进程下面成为僵尸进程。

    看另外一种情况,我们把sleep(1000)放到子进程的exit(0) 前面,同时去掉父进程中的sleep(1000)。

    结果如下:

    这个时候父进程早就运行完毕退出了,哈哈,但是子进程还没有运行完咋办,这个时候 1 号进程id接管这个进程,等他们运行完毕,在将他们清除掉。

    上面那样肯定是不好的,子进程就相当与父进程的孩子,父进程把他们创建出来了,却不负责清除他们,这怎么能行呢?谁创建谁销毁。

    那么我们就可以这样去写:

    使用一个wait 函数,等待子进程运行完毕,然后将子进程销毁之后,在退出程序!

    关于fork() 函数就先说道这….

    转载请注明原文地址: https://ju.6miu.com/read-37583.html

    最新回复(0)