fork 生成的子进程与父进程关系探究

fork 生成的子进程与父进程关系探究

MacOS/Linux下fork

父进程与子进程的关系,在不同操作系统下是不一样的,先讨论在 MacOS 或者 Linux 系统下,我们可以使用fork()来探索父子进程的关系。

fork 可以生成一个与当前进程完全一样的子进程,如果当前进程是父进程,fork()返回的是进程的pid,如果是子进程则会返回0

import os

print('Process (%s) start...' % os.getpid())
# Only works on Unix/Linux/Mac:

pid = os.fork()  # fork 时间点,父子进程完全一样
if pid == 0:  # 子进程永远返回0
    print('I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid()))
else:  # 父进程返回子进程的ID
    print('I (%s) just created a child process (%s).' % (os.getpid(), pid))
  
# Process (79869) start...
# I (79869) just created a child process (79870).
# I am child process (79870) and my parent is 79869.

fork 时完全一样

子进程会得到所有父进程资源的副本,包括进程PCB中的内容(除了 pid ),也就是甚至连下一条执行的指令都是完全一样的,所以子进程是从 fork 继续执行,而不是从头执行。

因为 fork 时完全一样,所以并没有像想象中一样每个子进程也会不断生成3个子进程。因为 fork 出来的子进程是完全一样的,连 for 循环中的 i 值也是一样的。

import os
import time

print('Process (%s) start...' % os.getpid())
# Only works on Unix/Linux/Mac:
val = 0
print("I am root process ({})", os.getpid())
for i in range(3):
    pid = os.fork()
    if pid == 0:
        print("created a process ({})".format(os.getpid()))

time.sleep(20)  # 等会再退出,便于使用 pstree 观察

iShot2022-03-17 17.38.03

pstree -p 82258 # 查看父子进程关系

iShot2022-03-17 17.39.01

fork 后不共享内存

父子进程不共享内存,fork()之后两者再无瓜葛,当然子进程可以通过 getppid 找到父进程。

因为不共享内存,所以父进程中 val 值没有更改。

import os
import time

print('Process (%s) start...' % os.getpid())
# Only works on Unix/Linux/Mac:
val = 0
pid = os.fork()  # fork 时间点,父子进程完全一样
if pid == 0:  # 子进程永远返回0
    while True:
        val += 1
        print('I am child process ({}). Value is {}'.format(os.getpid(), val))
        time.sleep(1)
else:  # 父进程返回子进程的ID
    while True:
        print('I am parent process ({}). Value is {}'.format(os.getpid(), val))
        time.sleep(1)

iShot2022-03-17 17.19.33

父进程创建子进程和主程序调用子程序的不同?

不同OS中父子进程的执行策略不同,一般来说,父进程创建子进程后,父子进程并发执行,而主程序调用子程序后,主程序会停在调用语句,等待子程序返回,才会从调用语句的下一句开始执行。

windows 下实现 fork

在windows,如何实现fork()函数-CSDN社区

在Windows系统下没有一个函数可以实现UNIX下的fork()函数,其原因是历史造成的,对于UNIX来说它一出生就是多用户的系统,所以它的所有进程都共有一个最原始的根进程(比如,上面 pstree 那张图中的 root 就是在 mac 下的根进程)。而windows生下来时是个单用户单任务系统(DOS),不存在这样的概念。

WIN32API函数CreateProcess用来创建一个新的进程和它的主线程,这个新进程运行指定的可执行文件。

在Windows下,如果想要模拟fork(),可以创建一个线程,把主线程中的公共变量

如果硬要模似,CreateProcess()不如用CreateThread()更接近实际情况,把主thread中的所有公共变量都塞入一个结构/类的,带入新的thread中,这样可以大致完成"复制自身"的要求。但由于是thread,所以主thread死后,子thread不能独立存在,而fork()出来的子进程可以脱离主进程独立存在,这一点在window下只有CreateProcess()才略有相似之处。

在WINDOWS系统中,子进程是个什么样的概念啊?-CSDN社区

linux维护一个进程关系列表,而windows一般并不维护,换句话说windows的进程无法知道自己的子进程有哪些,父进程又是谁。windows下父子进程发生关系只在调用CreateProcess的那一瞬间。
linux创建子进程是父进程的拷贝,一般拥有父进程所能够访问的资源。windows创建子进程不是这样子,不特殊指定,子进程不能使用父进程的资源。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
进程中,可以使用`waitpid`函数来等待子进程的结束,然后重新启动一个新的子进程。具体的步骤如下: 1. 在进程中使用`fork`函数创建一个子进程。 2. 在子进程中使用`execl`函数执行需要运行的程序。 3. 在进程中使用`waitpid`函数等待子进程结束。 4. 如果子进程正常结束,则使用`WIFEXITED`宏判断是否正常退出;如果子进程被信号终止,则使用`WIFSIGNALED`宏判断是否被信号终止。 5. 如果子进程正常结束或者被信号终止,则在进程中重新使用`fork`函数创建一个新的子进程并执行需要运行的程序。 代码示例: ``` #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> int main() { pid_t pid; int status; while (1) { pid = fork(); if (pid == -1) { perror("fork"); exit(EXIT_FAILURE); } else if (pid == 0) { execl("/path/to/program", "program", NULL); perror("execl"); exit(EXIT_FAILURE); } else { waitpid(pid, &status, 0); if (WIFEXITED(status)) { printf("Child process exited with status %d\n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("Child process terminated by signal %d\n", WTERMSIG(status)); } } } return 0; } ``` 在这个示例中,进程会不断地创建子进程并等待子进程结束。如果子进程正常结束,则在进程中重新创建一个新的子进程并执行需要运行的程序。如果子进程被信号终止,则在进程中也重新创建一个新的子进程并执行需要运行的程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值