linux系统编程-进程

进程

现实生活中

在很多的场景中的事情都是同时进行的,比如开车的时候 手和脚共同来驾驶汽车,再比如唱歌跳舞也是同时进行的;

如下是一段视频,迈克杰克逊的一段视频:

http://v.youku.com/v_show/id_XMzE5NjEzNjA0.html?&sid=40117&from=y1.2-1.999.6

试想:如果把唱歌和跳舞这2件事分开以此完成的话,估计就没有那么好的效果了

程序中

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

 11 from time import sleep
 12
 13 def sing():
 14     for i in range(3):
 15         print(‘正在唱歌...%d‘%i)
 16         sleep(1)
 17
 18 def dance():
 19     for i in range(3):
 20         print(‘正在跳舞...%d‘%i)
 21         sleep(1)
 22
 23 if __name__=="__main__":
 24     sing()
 25     dance()

运行结果如下:

正在唱歌...0
正在唱歌...1
正在唱歌...2
正在跳舞...0
正在跳舞...1
正在跳舞...2

注意!!!

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

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

多任务的概念

  什么叫做多任务呢?简单的说,就是操作系统可以同时运行多个任务。打个比方,你一边用浏览器上网,一边在听mp3,一边在赶word作业,这就是多任务,至少同时有3个任务正在运行。很有很多任务悄悄的在后台同时运行着,只是桌面上没有显示而已。

  现在,多核CPU已经非常普及了,但是,即使过去的单核CPU,也可以执行多任务。由于CPU执行代码都是顺序执行的,那么单核CPU是怎么执行多任务的呢?

  答案就是操作系统轮流让各个任务交替执行,任务1执行0.01秒, 切换到任务2,任务2执行0.01秒,切换到任务3,执行0.01秒......,这样反复的执行下去。表面上看,每个任务都是交替执行的,但是,由于CPU的执行速度实在是太快了,我们就感觉所有任务都在同时执行一样。

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

  单核CPU完成多个任务的执行的原因?

  •     时间片论法
  •     优先级调度

并行和并发

  并发:看上去一直执行

  并行:真正的一起执行

进程的创建-fork

进程VS程序

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

正在运行的代码,就称为 进程

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

fork()

python的os模块封装了常见的系统调用,其中就包括fork,可以在python程序中轻松创建子进程:

 11 import os
 12
 13 pid = os.fork()  #使用os.fork创建出一个新的进程,以下的代码父子进程都会执行
 14
 15 if pid == 0:
 16     print(‘哈哈0‘)
 17 else:
 18     print(‘哈哈1‘)  

运行结果如下:

哈哈1
哈哈0

还有一个例子:

 11 import os
 12 import time
 13
 14 ret = os.fork()
 15 if ret==0:
 16     while True:
 17         print(‘------------1-------------‘)
 18         time.sleep(1)
 19 else:
 20     while True:
 21         print(‘------------2-------------‘)
 22         time.sleep(1)

运行结果如下:

------------2-------------
------------1-------------
------------1-------------
------------2-------------
------------1-------------
------------2-------------
------------2-------------
------------1-------------
......

相当于程序在运行到了os.fork()时,产生了一个新的进程,ret用来接受两个进程返回值,旧的进程执行最下面的语句,而新的进程去执行上面的语句,因为新的进程的返回值为0。之前的进程称之为父进程,新创建出来的进程叫做子进程。

因为要分辨出父进程和子进程,所以操作系统给父进程的返回值大于0,给子进程的返回值等于0。

操作系统调度算法决定了父进程和子进程的运行顺序。

说明:

  • 程序执行到os.fork(),操作系统会创建一个新的进程(子进程),然后复制父进程的所有信息到子进程中
  • 然后父进程和子进程都会从fork()函数中得到一个返回值,在子进程中这个值一定是0,而父进程中是子进程的id号

在Unix/Linux操作系统中,提供了一个fork()函数,它非常特殊。

普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。

子进程永远返回0,而父进程返回子进程的ID号。

这样做的理由是:一个父进程可以fork出很多的子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用getppid()就可以拿到父进程的ID。

fork的返回值

 11 import os
 12
 13 ret = os.fork()
 14 print(ret)  

运行结果:

26517   #代表着父进程
0    #代表子进程

getpid()、getppid()

getpid()获取当前进程的值,getppid()获取当前进程的父进程的值。

 12 import os
 13 pid = os.fork()
 14
 15 if pid<0:
 16     print(‘fork调用失败.‘)
 17 elif pid==0:
 18     print(‘我是子进程(%s),我的父进程是(%s)‘%(os.getpid(),os.getppid()))
 19 else:
 20     print(‘我是父进程(%s),我的子进程是(%s)‘%(os.getppid(),os.getpid()))
 21
 22 print(‘ 父子进程都可以执行的代码<F8>‘) 

运行结果如下:

我是父进程(2774),我的子进程是(25874)
 父子进程都可以执行的代码<F8>
我是子进程(25875),我的父进程是(25874)
 父子进程都可以执行的代码<F8>

第二个例子:

 11 import os 12 pid = os.fork() 13 print(pid) 14       15 if pid>0: 16     print(‘父进程:%d‘%os.getpid()) 17 else: 18     print(‘子进程:%d-%d‘%(os.getpid(),os.getppid()))

运行结果:

26685   #pid的返回值,操作系统为了管理给它的值,父类的返回值,就是子进程的ID号 
父进程:26684  #26684是父进程ID号
0
子进程:26685-26684  #26685是子进程ID号,子进程的父进程是26684

多进程修改全局变量

 11 import os
 12 import time
 13
 14 num = 0
 15
 16 pid = os.fork()
 17
 18 if pid==0:
 19     num+=1
 20     print(‘哈哈1------num=%d‘%num)
 21 else:
 22     time.sleep(2)
 23     num+=1
 24     print(‘哈哈2------num=%d‘%num)

运行结果如下:

哈哈1------num=1
哈哈2------num=1

说明:

  • 在多进程中,每个进程中的数据(包含全局变量)都各自拥有一份,互不影响,进程和进程之间不会数据共享

多次fork问题

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

 11 import os
 12 import time
 13
 14 pid = os.fork()
 15 if pid==0:
 16     print(‘哈哈1‘)
 17 else:
 18     print(‘哈哈2‘)    #一共运行了2次
 19
 20 pid = os.fork()
 21 if pid==0:
 22     print(‘哈哈3‘)
 23 else:
 24     print(‘哈哈4‘)    #一共运行了4次
 25
 26 time.sleep(1)      

运行结果如下:

[email protected]:~/codes/liunx系统编程/01-进程$ python 05-多次fork调用.py
哈哈2
哈哈1
哈哈4
哈哈4
哈哈3
哈哈3

说明:

父子进程的执行顺序

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

 11 import os
 12 import time
 13 ret = os.fork()
 14
 15 if ret==0:
 16     print(‘子进程‘)
 17     time.sleep(1)
 18     print(‘子进程over‘)    #end=""
 19 else:
 20     print(‘父进程‘)

运行结果如下:

python3 04-父子进程的运行顺序.py
父进程
子进程
[email protected]:~/codes/liunx系统编程/01-进程$ 子进程over  

因为父进程已经结束了,意味着终端已经可以开始提示了,所以当父进程一执行完,那么终端就会立马出来。

多任务的优点

增加程序的运行效率,例如爬虫

multiprocessing

如果打算编写多进程的服务程序,Unix和Linux无疑是正确的选择。由于windows没有fork调用,难道在 windows上无法用python编写多进程的程序?

由于python是跨平台的,自然也应该提供一个跨平台的多进程支持,multiprocess模块就是跨平台版本的多进程模块。

multiprocessessing模块提供了一个Process类来代表一个进程对象,下面的例子演示了启动一个子进程并等待其结束:

原文地址:https://www.cnblogs.com/xiaoyafei/p/8761848.html

时间: 2024-10-09 08:45:40

linux系统编程-进程的相关文章

Linux系统编程@进程通信(一)

进程间通信概述 需要进程通信的原因: 数据传输 资源共享 通知事件 进程控制 Linux进程间通信(IPC)发展由来 Unix进程间通信 基于System V进程间通信(System V:UNIX系统的一个分支) POSIX进程间通信(POSIX:可移植操作系统接口,为了提高UNIX环境下应用程序的可移植性.很多其他系统也支持POSIX标准(如:DEC OpenVMS和Windows).) 现在Linux使用的进程间通信方式包括: 管道(pipe).有名管道(FIFO) 信号(signal) 消

Linux系统编程——进程管理

引言: 在Linux的内核的五大组成模块中,进程管理模块时非常重要的一部分,它虽然不像内存管理.虚拟文件系统等模块那样复杂,也不像进程间通信模块那样条理化,但作为五大内核模块之一,进程管理对我们理解内核的运作.对于我们以后的编程非常重要.同时,作为五大组成模块中的核心模块,它与其他四个模块都有联系.下面就对进程模块进行想写的介绍,首先要了解进程及其相关的概念.其次介绍进程的创建.切换.撤销等基本操作.除此之外,还给出了Linux内核是如何对进程进行调度管理的.      一.进程及其相关概念 进

Linux系统编程——进程替换:exec 函数族

在 Windows 平台下.我们能够通过双击运行可运行程序.让这个可运行程序成为一个进程:而在 Linux 平台.我们能够通过 ./ 运行,让一个可运行程序成为一个进程. 可是,假设我们本来就执行着一个程序(进程),我们怎样在这个进程内部启动一个外部程序.由内核将这个外部程序读入内存,使其执行起来成为一个进程呢?这里我们通过 exec 函数族实现. exec 函数族.顾名思义.就是一簇函数,在 Linux 中,并不存在 exec() 函数.exec 指的是一组函数.一共同拥有 6 个: [cpp

Linux系统编程——进程的控制:结束进程、等待进程结束

结束进程 首先,我们回顾一下 C 语言中 continue, break, return 的作用: continue: 结束本次循环 break: 跳出整个循环,或跳出 switch() 语句 return: 结束当前函数 而我们可以通过 exit() 或 _exit() 来结束当前进程. 所需头文件: #include <stdlib.h> void exit(int value); 功能: 结束调用此函数的进程. 参数: status:返回给父进程的参数(低 8 位有效),至于这个参数是多

Linux系统编程——进程和线程的区别与联系

在许多经典的操作系统教科书中,总是把进程定义为程序的执行实例,它并不执行什么, 只是维护应用程序所需的各种资源,而线程则是真正的执行实体. 为了让进程完成一定的工作,进程必须至少包含一个线程. 进程,直观点说,保存在硬盘上的程序运行以后,会在内存空间里形成一个独立的内存体,这个内存体有自己的地址空间,有自己的堆,上级挂靠单位是操作系统.操作系统会以进程为单位,分配系统资源,所以我们也说,进程是资源分配的最小单位.更多详情,请看<进程的介绍>. 线程存在与进程当中,是操作系统调度执行的最小单位.

linux系统编程--进程相关概念

程序和进程 程序:二进制文件,占用的磁盘空间,还没运行 进程:启动的程序,数据在内存中,占用系统资源(CPU,物理内存) 并行和并发 并发:不是一个时间点的概念,而是一个时间段的概念,某个时间段内处理的请求数量 并行:增加服务器或cpu对请求的处理 一个cpu把一个时间段分成若干时间碎片,每个时间碎片只能处理一个进程,交替的处理进程 pcb(进程控制块) 常见内部成员: - 进程id - 进程的状态:初始,就绪,运行,挂起,终止 - 进程切换时,需要保存和恢复一些CPU寄存器 - 描述虚拟地址空

Linux系统编程——进程的介绍

http://my.9ku.com/fuyin/daogaoo.asp?dgid=564516 http://my.9ku.com/fuyin/daogaoo.asp?dgid=564608 http://my.9ku.com/fuyin/daogaoo.asp?dgid=564687 http://my.9ku.com/fuyin/daogaoo.asp?dgid=564782 http://my.9ku.com/fuyin/daogaoo.asp?dgid=564867 http://my.

Linux系统编程札记:进程通信(一) &nbsp; &nbsp;

进程简单来讲就是一个程序的一次执行,这里说的进程一般都指的是运行在用户态的进程,而处于用户态的不同进程之间是彼此相互隔离的,它们必须通过某种方式来进行通信,具体理由如下: (1)数据传输:有时候一个进程需要将它的数据发送给另一个进程. (2)资源共享:有时候多个进程之间需要共享同样的资源. (3)通知事件:有时候一个进程需要向另一个或一组进程发送消息,通知它们发生了某个事件. (4)进程控制:有些进程希望能够完全控制另一个进程的执行,此时控制进程希望能够拦截另一进程的所有操作,并能够及时知道它的

Linux系统编程之进程

前一段时间对文件I/O的基本操作基本操作做了总结,今天这里继续按照我的理解对linux系统编程的进程操作进行总结. 首先我们先理解几个概念:程序.进程.线程. 所谓程序,就是计算机指令的集合,它以文件的形式存储在磁盘上,进程是一个程序在其自身的地址空间中的一次执行活动.而线程进程内的一个执行单元,也是进程内的可调度实体.说完这个不知道大家理解了吗?反正我第一次听到这个概念以后看到的时候可以明白过后就忘记了,现在我给大家举一个例子帮助大家理解,大家都看电视剧吧,所谓程序,就是一个剧本,像什么<西游