从一道面试题来学习前台进程和后台进程/孤儿进程和僵尸进程

科技资讯 投稿 24200 0 评论

从一道面试题来学习前台进程和后台进程/孤儿进程和僵尸进程

1、面试题介绍

我们在终端中,通过执行 python main.py 命令,会启动一台前台进程直到程序结束。现在我还是想通过执行 python main.py,启动一个后台进程,让后台进程运行我们的业务逻辑。这个时候应该怎么做呢?

2、前台进程和后台进程

2.1 什么是前台进程

在 Linux 中,前台进程是指当前正在运行的进程,它与用户交互并占用终端。当用户在终端中输入命令时,该命令所启动的进程就是前台进程。

前台进程会占用终端,直到它执行完毕或者被中断(例如按下 Ctrl+C)。在前台进程运行期间,用户可以通过键盘输入命令或者发送信号来与进程交互。

2.2 什么是后台进程

后台进程是指在终端中运行的进程,但是不会占用终端的输入输出,而是在后台运行。

command & 就可以将 command 进程放到后台运行。

jobs 命令查看当前运行的后台进程,使用 fg 命令将后台进程切换到前台运行,使用 bg 命令将前台进程切换到后台运行。

tail 命令实时查看输出。

2.3 前台进程、后台进程如何切换

    使用 Ctrl + Z 将当前正在运行的前台进程挂起。
  1. 使用 bg 命令将挂起的进程切换到后台运行。

使用 command &,这样的方式是一开始就将 command 进程放到后台运行。

1、编写 test.py文件。

import os
import time


def main(:
    a = 1
    while True:
        time.sleep(1
        a += 1
        print("a---->", a
        if a > 30:
            break


if __name__ == '__main__':
    main(

2、通过 python test.py执行程序。然后使用ctrl + Z 是程序暂停到后台。注意,这个时候程序不会再往下执行了。

    bg 命令将其切换到后台运行。

  • &。即python main.py &

python test.py
a----> 2
a----> 3
^Z
[1]  + 1761 suspended  python test.py
sample_test [master●] %

3、通过jobs命令查询后台进程。

sample_test [master●] % jobs          
[1]  + suspended  python test.py
sample_test [master●] %

4、使用fg命令将指定的后台进程切换到前台运行。(fg %N,这里的N是 jobs返回的序号,并不是进程的PID)

    
sample_test [master●] % fg %1     
[1]  + 1761 continued  python test.py
a----> 4
a----> 5
a----> 6
a----> 7

3、孤儿进程和僵尸进程

通过上面的讲解,我们知道了什么是后台进程和前台进程。接下来,我们再讲讲什么是孤儿进程和僵尸进程。

3.1 什么是孤儿进程

孤儿进程是指父进程已经结束或者异常退出,而子进程还在运行的情况下,子进程就会变成孤儿进程。孤儿进程会被操作系统的init进程接管init进程会成为孤儿进程的新的父进程,并负责回收孤儿进程的资源,避免资源泄露和浪费。

我们来看一个关于孤儿进程的例子:

import os
import time


def main(:
    pid = os.fork(  # 创建子进程
    if pid < 0:
        # 创建失败
        print("fork failed!"
        exit(1
    elif pid == 0:  # 子进程
        print("I am the child process."
        print("pid:%d, ppid:%d " % (os.getpid(, os.getppid(
        # 子进程睡眠3s,保证父进程先退出,此后子进程成为孤儿进程
        time.sleep(3
        # 注意查看孤儿进程的父进程变化
        print("after sleep, pid:%d, ppid:%d" % (os.getpid(, os.getppid(
        assert os.getppid( == 1
        print("child process is exited."
    else:
        print("I am father process."
        # 为保证子进程先运行,让父进程睡眠1s
        time.sleep(1
        print("father process is exited."




if __name__ == '__main__':
    main(

执行结果:

3.2 什么是僵尸进程

Linux 僵尸进程是指已经结束执行的进程,但是其父进程还没有对其进行处理,导致该进程的进程描述符仍然存在于系统中,这种进程被称为僵尸进程

为了避免僵尸进程的出现,父进程需要及时对其进行处理,可以使用 wait( 或 waitpid( 等系统调用来等待子进程结束并回收其资源。另外,也可以使用信号处理机制,在父进程中注册 SIGCHLD 信号处理函数来处理子进程结束的信号。

僵尸进程的例子:

import os
import time


def main(:
    pid = os.fork(  # 创建子进程
    if pid < 0:
        # 创建失败
        print("fork failed!"
        exit(1
    elif pid == 0:  # 子进程
        print("I am the child process.I am exited."
        exit(0
    else:
        print("I am father process."
        #  父进程睡眠30s等待子进程退出,且没有调用wait/waitpid获取其状态
        #  子进程会成为僵尸进程
        time.sleep(30
        print("father process is exited."




if __name__ == '__main__':
    main(

开一个终端,在终端是运行test.py

注意:

    任何一个子进程(init除外在exit(之后,其实它并没有真正的被销毁,而是留下一个称为僵尸进程(Zombie的数据结构,等待父进程处理。这是每个子进程在结束时都要经过的阶段。
  1. 如果子进程在exit(之后,父进程没有来得及处理,这时用ps命令就能看到子进程的状态是“Z”。如果父进程能及时处理,可能用ps命令就来不及看到子进程的僵尸状态,但这并不等于子进程不经过僵尸状态。
  2. 如果父进程在子进程结束之前退出,则子进程将由init接管。init将会以父进程的身份对僵尸状态的子进程进行处理。
  3. 如果父进程是一个循环,不会结束,那么子进程就会一直保持僵尸状态,这就是系统中有时候会有很多僵尸进程的原因。

3.3 总结

    孤儿进程:父进程已亡,子进程成为孤儿,被init进程收养,由init进程对它们完成状态收集工作,因此一般没有坏的影响。
  • 僵尸进程:子进程已亡,父进程没给子进程收尸,子进程成为僵尸进程,占用系统资源。

4、面试题解决方式

现在再回过头来看 面试题的要求:

python main.py命令,启动后台进程来进行业务处理。

1、通过 os.fork(创建子进程。

简单案例:

import os
import time


def main(:
    pid = os.fork(  # 创建子进程
    a = 0
    if pid < 0:
        # 创建失败
        print("fork failed!"
        exit(1
    elif pid == 0:  # 子进程
        for i in range(10:
            time.sleep(1
            a += i
        print("child process calculate result: %d" % a
    else:
        print("I am father process."
        exit(0


if __name__ == '__main__':
    main(
sample_test [master●] % python test.py
I am father process.


10秒钟过后
sample_test [master●] % child process calculate result: 45

参考资料:

僵尸进程与孤儿进程

编程笔记 » 从一道面试题来学习前台进程和后台进程/孤儿进程和僵尸进程

赞同 (120) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽