Python 之小白的系统进程的理解之fork篇

系统编程介绍:

之前程序执⾏都是⼀条腿⾛路,甚⾄是⽤⼀杆枪来打天下,通过系统编程的学习,会让大家有“”多条腿“”一起走路,就好比有了一把机关枪。

进程

现实生活中:

      有很多的场景中的事情是同时进⾏的,⽐如开⻋的时候 ⼿和脚共同来驾驶汽⻋,再⽐如唱歌跳舞也是同时进⾏的;试想,如果把唱歌和跳舞这2件事情分开依次完成的话,估计就没有那么好的效果了(想⼀下场景:先唱歌,然后在跳舞,O(∩_∩)O哈哈~)

程序中:

        如下程序,来模拟“唱歌跳舞”这件事情

        

from time import sleep
def sing():
    for i in range(3):
        print("正在唱歌...%d"%i)
        sleep(1)
def dance():
    for i in range(3):
        print("正在跳舞...%d"%i)
        sleep(1)
if __name__ == '__main__':
    sing()  # 唱歌
    dance()  # 跳舞

运行结果如下:


很显然刚刚的程序并没有完成唱歌和跳舞同时进⾏的要求

如果想要实现“唱歌跳舞”同时进⾏,那么就需要⼀个新的⽅法,叫做:多任务

多任务的概念

什么叫“多任务”呢?简单地说,就是操作系统可以同时运⾏多个任务。打个⽐⽅,你⼀边在⽤浏览器上⽹,⼀边在听MP3,⼀边在⽤Word赶作业,这就

是多任务,⾄少同时有3个任务正在运⾏。还有很多任务悄悄地在后台同时运⾏着,只是桌⾯上没有显示⽽已。

现在,多核CPU已经⾮常普及了,但是,即使过去的单核CPU,也可以执⾏多任务。由于CPU执⾏代码都是顺序执⾏的,那么,单核CPU是怎么执⾏多
任务的呢?
答案就是操作系统轮流让各个任务交替执⾏,任务1执⾏0.01秒,切换到任务2,任务2执⾏0.01秒,再切换到任务3,执⾏0.01秒……这样反复执⾏下去。

表⾯上看,每个任务都是交替执⾏的,但是,由于CPU的执⾏速度实在是太快了,我们感觉就像所有任务都在同时执⾏⼀样。

真正的并⾏执⾏多任务只能在多核CPU上实现,但是,由于任务数量远远多于CPU的核⼼数量,所以,操作系统也会⾃动把很多任务轮流调度到每个核⼼上执⾏。

进程的创建-fork

1. 进程 VS 程序

编写完毕的代码,在没有运⾏的时候,称之为程序

正在运⾏着的代码,就成为进程

进程,除了包含代码以外,还有需要运⾏的环境等,所以和程序是有区别的

2. fork( )

Python的os模块封装了常⻅的系统调⽤,其中就包括fork,可以在Python程序中轻松创建⼦进程:


import os
# 注意,fork函数,只在Unix/Linux/Mac上运⾏,windows不可以
pid = os.fork()

    if pid == 0:

        print('哈哈1')
    else:

        print('哈哈2')

运行的结果是:“”哈哈2“”

                    “”哈哈1“”

说明:程序执⾏到os.fork()时,操作系统会创建⼀个新的进程(⼦进程),然后复制⽗进程的所有信息到⼦进程中

然后⽗进程和⼦进程都会从fork()函数中得到⼀个返回值,在⼦进程中这个值⼀定是0,⽽⽗进程中是⼦进程的 id号

在Unix/Linux操作系统中,提供了⼀个fork()系统函数,它⾮常特殊。普通的函数调⽤,调⽤⼀次,返回⼀次,但是fork()调⽤⼀次,返回两次,因为操作系统⾃动把当前进程(称为⽗进程)复制了⼀份(称为⼦进程),然后,分别在⽗进程和⼦进程内返回。⼦进程永远返回0,⽽⽗进程返回⼦进程的ID。这样做的理由是,⼀个⽗进程可以fork出很多⼦进程,所以,⽗进程要记下

每个⼦进程的ID,⽽⼦进程只需要调⽤getppid()就可以拿到⽗进程的ID。


3. getpid()、getppid()

import os
rpid = os.fork()
if rpid<0:
    print("fork调⽤失败。")
elif rpid == 0:
    print("我是⼦进程(%s),我的⽗进程是(%s)"%(os.getpid(),os.getppid()))
    x+=1
else:
    print("我是⽗进程(%s),我的⼦进程是(%s)"%(os.getpid(),rpid))
    print("⽗⼦进程都可以执⾏这⾥的代码")

运行结果:

我是⽗进程(19360),我的⼦进程是(19361)
⽗⼦进程都可以执⾏这⾥的代码

我是⼦进程(19361),我的⽗进程是(19360)
⽗⼦进程都可以执⾏这⾥的代码

多进程修改全局变量

import os
import time
num = 0
# 注意,fork函数,只在Unix/Linux/Mac上运⾏,windows不可以
pid = os.fork()
    if pid == 0:
    num+=1
    print('哈哈1---num=%d'%num)
else:
    time.sleep(1)
    num+=1
print('哈哈2---num=%d'%num)
运行结果是:哈哈1---num=1
                    哈哈2---num=1

                    哈哈2---num=1

总结:

多进程中,每个进程中所有数据(包括全局变量)都各有拥有⼀份,互不影响

多次fork问题

如果在⼀个程序,有2次的fork函数调⽤,是否就会有3个进程呢?

#coding=utf-8
import os
import time
# 注意,fork函数,只在Unix/Linux/Mac上运windows不可以
pid = os.fork()
if pid == 0:
    print('哈哈1')
else:
    print('哈哈2')
pid = os.fork()
if pid == 0:
    print('哈哈3')
else:
    print('哈哈4')
    time.sleep(1)

运行结果:

哈哈2
哈哈4
哈哈3
哈哈1
哈哈4
哈哈3

说明:


⽗⼦进程的执⾏顺序

⽗进程、⼦进程执⾏顺序没有规律,完全取决于操作系统的调度算法






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值