fork进程后的程序流程

使用fork创建子进程后,子进程会复制父进程的数据信息,而后程序就分两个进程继续运行后面的程序,这也是fork(分叉)名字的含义了。在子进程内,这个方法会返回0;在父进程内,这个方法会返回子进程的编号PID。可以使用PID来区分两个进程:

#!/usr/bin/env python
#coding=utf8import os#创建子进程之前声明的变量
source = 10try:pid = os.fork()if pid == 0: #子进程print "this is child process."#在子进程中source自减1source = source - 1sleep(3)else: #父进程print "this is parent process."print source
except OSError, e:pass

上面代码中,在子进程创建前,声明了一个变量source,然后在子进程中自减1,最后打印出source的值,显然父进程打印出来的值应该为10,子进程打印出来的值应该为9。为了明显区分父进程和子进程,让子进程睡3秒,就看的比较明显了。

既然子进程是父进程创建的,那么父进程退出之后,子进程会怎么样呢?此时,子进程会被PID为1的进程接管,就是init进程了。这样子进程就不会受终端退出影响了,使用这个特性就可以创建在后台执行的程序,俗称守护进程(daemon)。

---------------------

import os  def child():  print 'A new child:', os.getpid()  print 'Parent id is:', os.getppid()  os._exit(0)  def parent():  while True:  newpid=os.fork()  print newpid  if newpid==0:  child()  else:  pids=(os.getpid(),newpid)  print "parent:%d,child:%d"%pids  print "parent parent:",os.getppid()         if raw_input()=='q':  break  parent()  

在我们加载了os模块之后,我们parent函数中fork()函数生成了一个子进程,返回值newpid有两个,一个为0,用以表示子进程,一个是大于0的整数,用以表示父进程,这个常数正是子进程的pid. 通过print语句我们可以清晰看到两个返回值。如果fork()返回值是一个负值,则表明子进程生成不成功(这个简单程序中没有考虑这种情况)。如果newpid==0,则表明我们进入到了子进程,也就是child()函数中,在子进程中我们输出了自己的id和父进程的id。如果进入了else语句,则表明newpid>0,我们进入到父进程中,在父进程中os.getpid()得到自己的id,fork()返回值newpid表示了子进程的id,同时我们输出了父进程的父进程的id. 通过实验我们可以看到if和else语句的执行顺序是不确定的,子、父进程的执行顺序由操作系统的调度 算法 来决定。

----------

#!/usr/bin/env python
#coding=utf8import os, sys, time#产生子进程,而后父进程退出
pid = os.fork()
if pid > 0:sys.exit(0)#修改子进程工作目录
os.chdir("/")
#创建新的会话,子进程成为会话的首进程
os.setsid()
#修改工作目录的umask
os.umask(0)#创建孙子进程,而后子进程退出
pid = os.fork()
if pid > 0:sys.exit(0)#重定向标准输入流、标准输出流、标准错误
sys.stdout.flush()
sys.stderr.flush()
si = file("/dev/null", 'r')
so = file("/dev/null", 'a+')
se = file("/dev/null", 'a+', 0)
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())#孙子进程的程序内容
while True:time.sleep(10)f = open('/home/test.txt', 'a')f.write('hello')

上面的程序没有任何错误处理,但是不影响原理分析。如果要应用到项目里,还需完善。下面笔者谈下自己对每个步骤的理解。

1、fork子进程,父进程退出

通常,我们执行服务端程序的时候都会通过终端连接到服务器,成功连接后会加载shell环境,终端和shell都是进程,shell进程是终端进程的子进程,通过ps命令可以很容易的查看到。在这个shell环境下一开始执行的程序都是shell进程的子进程,自然会受到shell进程的影响。在程序里fork子进程后,父进程退出,对了shell进程来说,这个父进程就算执行完了,而产生的子进程会被init进程接管,从而也就脱离了终端的控制。

2、修改子进程的工作目录

子进程在创建的时候会继承父进程的工作目录,如果执行的程序是在u盘里的,就会导致u盘不能卸载。

3、创建新会话

使用setsid后,子进程就会成为新会话的首进程(session leader);子进程会成为新进程组的组长进程;子进程没有控制终端。

4、修改umask

由于umask会屏蔽权限,所以设定为0,这样可以避免读写文件时碰到权限问题。

5、fork孙子进程,子进程退出

经过上面几个步骤后,子进程会成为新的进程组老大,可以重新申请打开终端,为了避免这个问题,fork孙子进程出来。

6、重定向孙子进程的标准输入流、标准输出流、标准错误流到/dev/null

因为是守护进程,本身已经脱离了终端,那么标准输入流、标准输出流、标准错误流就没有什么意义了。所以都转向到/dev/null,就是都丢弃的意思。

python fork()创建新的进程,daemon进程相关推荐

  1. Python新建一个文件目录,python怎么创建新文件

    python怎么创建新文件 首先,进行打开的pycharm软件界面当中,进行选中已经打开的项目文件.请点击输入图片描述然后进行点击菜单中的"file"的选项菜单. 请点击输入图片描 ...

  2. python程序启动其他python程序_python中使用fork创建新的进程

    python中如果要创建新进程的话,可以使用os模块中的fork方法.为了了解其中工作原理,笔者结合linux的查看进程ps命令,对这个方法做了一些测试. python运行时进程 python一开始运 ...

  3. python中使用fork创建新的进程

    fork知识入门 python的os module中有fork()函数用于生成子进程,生成的子进程是父进程的镜像,但是它们有各自的地址空间,子进程复制一份父进程内存给自己,两个进程之间的执行是相互独立 ...

  4. python中fork创建新的进程

    为了了解其中工作原理, 在结合linux的查看进程ps命令,对进程做了进一步的理解: 1.在linux下运行.py文件,系统就会创建一个进程 # coding=utf-8 from time impo ...

  5. Linux中fork创建兄弟子进程,验证进程之间全局变量不共享,exec函数族

    文章目录 编程环境: 并行和并发: 并发:一个时间段,处理请求的个数 并行:多个进程同时进行任务分配: PCB 和 进程的五种状态: 进程控制块 PCB: 进程的五种状态: 进程控制块,父进程创建子进 ...

  6. python不能创建新变量_Python之变量的创建过程!

    Python之变量的创建过程 一.变量创建过程 首先,当我们定义了一个变量name = 'Kwan'的时候,在内存中其实是做了这样一件事: 程序开辟了一块内存空间,将'Kwan'存储进去,再让变量名n ...

  7. python创造订单失败_使用Python API创建新订单,get AttributeError:“str”对象没有属性“iteritems”...

    我掌握的代码是new_order = shopify.Order.create(json.dumps({'order': { "email": "foo@example. ...

  8. Linux进程全解4——fork创建子进程

    以下内容源于朱有鹏<物联网大讲堂>课程的学习整理,如有侵权,请告知删除. 1.为什么要创建子进程? (1)每一次程序的运行都需要一个进程: (2)多进程实现宏观上的并行. 2.fork的内 ...

  9. 从整体上理解进程创建、可执行文件的加载和进程执行进程切换,重点理解分析fork、execve和进程切换...

    学号后三位<168> 原创作品转载请注明出处https://github.com/mengning/linuxkernel/ 1.分析fork函数对应的内核处理过程sys_clone,理解 ...

  10. Linux守护进程(daemon)

    0x0:守护进程(daemon) 守护进程(daemon)是一类在后台运行的特殊进程,用于执行特定的系统任务.很多守护进程在系统引导的时候启动,并且一直运行直到系统关闭.另一些只在需要的时候才启动,完 ...

最新文章

  1. Kubernetes删除一直处于Terminating状态的namespace
  2. uCOS-II任务建立示例
  3. 浅谈基于TCP和UDP的协议设计
  4. 【转载】浅谈 看图软件 的设计与实现
  5. USACO-Section1.4 Barn Repair (贪心算法)
  6. 添加mysql组合主键_mysql怎么添加复合主键?
  7. 春运,一场共享发展的旅程
  8. 数据库异常---ORA-01436: 用户数据中的 CONNECT BY loop in user data 循环
  9. linux重启memcache_linux下启动和停止memcached
  10. c++中vector用法(涵盖算法题中知识点)
  11. knn算法java版_KNN算法的实现详解
  12. JAVA Swing GUI设计 WindowBuilder Pro Container使用大全4——JSplitPane使用
  13. 陶哲轩实分析 习题 12.5.4,12.5.5
  14. jpython 传入参数_C++嵌入Python程序(二):参数传入及返回
  15. 前端web开发培训,HTML表格标签,先收藏了
  16. 没有云服务器?内网穿透了解一下
  17. 内存颗粒位宽和容量_高手进阶,终极内存技术指南(1)
  18. 专网网速测试软件,CMD怎么测试网速?测网速用命令PING
  19. 八位数字后加逗号_【PTE干货】英文数字的读法
  20. latex normal是几号字_Latex 文本详细篇

热门文章

  1. 软件工程和计算机科学考公务员,软件工程可以考公务员吗
  2. 2055013-55-1,Ald-Ph-PEG6-acid在EDC或HATU等活化剂存在下,末端羧酸可与伯胺偶联形成稳定的酰胺键
  3. 在本地运行scala程序报错 requirement failed: Can only call getServletHandlers on a running MetricsSystem
  4. iOS中百度地图API的总结
  5. pytorch 画loss曲线_Python练习绘制损失曲线,Pytorch,Loss
  6. Excel中快速删除换行
  7. 基于Github Actions + Docker + Git 的DevOps方案实践教程
  8. Android8.1 9.0 10.0 默认开启WLAN热点设置默认热点名称和密码
  9. 背单词App开发日记0
  10. 基于32feet.net对Broadcom(Widcomm) stack蓝牙(Bluetooth)设备开发Windows Mobile与PC程序