python fork()创建新的进程,daemon进程
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进程相关推荐
- Python新建一个文件目录,python怎么创建新文件
python怎么创建新文件 首先,进行打开的pycharm软件界面当中,进行选中已经打开的项目文件.请点击输入图片描述然后进行点击菜单中的"file"的选项菜单. 请点击输入图片描 ...
- python程序启动其他python程序_python中使用fork创建新的进程
python中如果要创建新进程的话,可以使用os模块中的fork方法.为了了解其中工作原理,笔者结合linux的查看进程ps命令,对这个方法做了一些测试. python运行时进程 python一开始运 ...
- python中使用fork创建新的进程
fork知识入门 python的os module中有fork()函数用于生成子进程,生成的子进程是父进程的镜像,但是它们有各自的地址空间,子进程复制一份父进程内存给自己,两个进程之间的执行是相互独立 ...
- python中fork创建新的进程
为了了解其中工作原理, 在结合linux的查看进程ps命令,对进程做了进一步的理解: 1.在linux下运行.py文件,系统就会创建一个进程 # coding=utf-8 from time impo ...
- Linux中fork创建兄弟子进程,验证进程之间全局变量不共享,exec函数族
文章目录 编程环境: 并行和并发: 并发:一个时间段,处理请求的个数 并行:多个进程同时进行任务分配: PCB 和 进程的五种状态: 进程控制块 PCB: 进程的五种状态: 进程控制块,父进程创建子进 ...
- python不能创建新变量_Python之变量的创建过程!
Python之变量的创建过程 一.变量创建过程 首先,当我们定义了一个变量name = 'Kwan'的时候,在内存中其实是做了这样一件事: 程序开辟了一块内存空间,将'Kwan'存储进去,再让变量名n ...
- python创造订单失败_使用Python API创建新订单,get AttributeError:“str”对象没有属性“iteritems”...
我掌握的代码是new_order = shopify.Order.create(json.dumps({'order': { "email": "foo@example. ...
- Linux进程全解4——fork创建子进程
以下内容源于朱有鹏<物联网大讲堂>课程的学习整理,如有侵权,请告知删除. 1.为什么要创建子进程? (1)每一次程序的运行都需要一个进程: (2)多进程实现宏观上的并行. 2.fork的内 ...
- 从整体上理解进程创建、可执行文件的加载和进程执行进程切换,重点理解分析fork、execve和进程切换...
学号后三位<168> 原创作品转载请注明出处https://github.com/mengning/linuxkernel/ 1.分析fork函数对应的内核处理过程sys_clone,理解 ...
- Linux守护进程(daemon)
0x0:守护进程(daemon) 守护进程(daemon)是一类在后台运行的特殊进程,用于执行特定的系统任务.很多守护进程在系统引导的时候启动,并且一直运行直到系统关闭.另一些只在需要的时候才启动,完 ...
最新文章
- Kubernetes删除一直处于Terminating状态的namespace
- uCOS-II任务建立示例
- 浅谈基于TCP和UDP的协议设计
- 【转载】浅谈 看图软件 的设计与实现
- USACO-Section1.4 Barn Repair (贪心算法)
- 添加mysql组合主键_mysql怎么添加复合主键?
- 春运,一场共享发展的旅程
- 数据库异常---ORA-01436: 用户数据中的 CONNECT BY loop in user data 循环
- linux重启memcache_linux下启动和停止memcached
- c++中vector用法(涵盖算法题中知识点)
- knn算法java版_KNN算法的实现详解
- JAVA Swing GUI设计 WindowBuilder Pro Container使用大全4——JSplitPane使用
- 陶哲轩实分析 习题 12.5.4,12.5.5
- jpython 传入参数_C++嵌入Python程序(二):参数传入及返回
- 前端web开发培训,HTML表格标签,先收藏了
- 没有云服务器?内网穿透了解一下
- 内存颗粒位宽和容量_高手进阶,终极内存技术指南(1)
- 专网网速测试软件,CMD怎么测试网速?测网速用命令PING
- 八位数字后加逗号_【PTE干货】英文数字的读法
- latex normal是几号字_Latex 文本详细篇
热门文章
- 软件工程和计算机科学考公务员,软件工程可以考公务员吗
- 2055013-55-1,Ald-Ph-PEG6-acid在EDC或HATU等活化剂存在下,末端羧酸可与伯胺偶联形成稳定的酰胺键
- 在本地运行scala程序报错 requirement failed: Can only call getServletHandlers on a running MetricsSystem
- iOS中百度地图API的总结
- pytorch 画loss曲线_Python练习绘制损失曲线,Pytorch,Loss
- Excel中快速删除换行
- 基于Github Actions + Docker + Git 的DevOps方案实践教程
- Android8.1 9.0 10.0 默认开启WLAN热点设置默认热点名称和密码
- 背单词App开发日记0
- 基于32feet.net对Broadcom(Widcomm) stack蓝牙(Bluetooth)设备开发Windows Mobile与PC程序