python语法笔记

【os】


【os.getpid(), os.fork()】

每个进程都有一个不重复的“进程ID号”,或称“pid”,它对进程进程进行标识。

进程调用fork函数时,操作系统会新建一个子进程,它本质上与父进程完全相同。

子进程接收返回值为0,而父进程接收子进程的pid作为返回值。

调用fork函数后,两个进程并发执行同一个程序,首先执行的是调用了fork之后的下一行代码。

父进程和子进程既并发执行,又相互独立;也就是说,它们是“异步执行”的。


【os.getcwd()】

取得当前目录。


【os.chdir(目录)】

更改当前目录。


【Python 实现的守护进程】

守护进程:通常被定义为一个后台进程,而且它不属于任何一个终端会话(terminal session)。许多系统服务由守护程序实施;如网络服务,打印等。

1. 调用fork()以便父进程可以退出,这样就将控制权归还给运行你程序的命令行或shell程序。需要这一步以便保证新进程不是一个进程组头领进程(process group leader)。下一步,‘setsid()’,会因为你是进程组头领进程而失败。
2. 调用‘setsid()’ 以便成为一个进程组和会话组的头领进程。由于一个控制终端与一个会话相关联,而且这个新会话还没有获得一个控制终端,我们的进程没有控制终端,这对于守护程序来说是一件好事。 
3. 再次调用‘fork()’所以父进程(会话组头领进程)可以退出。这意味着我们,一个非会话组头领进程永远不能重新获得控制终端。
4. 调用‘chdir("/")’确认我们的进程不保持任何目录于使用状态。不做这个会导致系统管理员不能卸装(umount)一个文件系统,因为它是我们的当前工作目录。 [类似的,我们可以改变当前目录至对于守护程序运行重要的文件所在目录] 
5. 调用‘umask(0)’以便我们拥有对于我们写的任何东西的完全控制。我们不知道我们继承了什么样的umask。 [这一步是可选的](译者注:这里指步骤5,因为守护程序不一定需要写文件)
6. 调用‘close()’关闭文件描述符0,1和2。这样我们释放了从父进程继承的标准输入,标准输出,和标准错误输出。我们没办法知道这些文描述符符可能 已经被重定向去哪里。注意到许多守护程序使用‘sysconf()’来确认‘_SC_OPEN_MAX’的限制。‘_SC_OPEN_MAX’告诉你每个 进程能够打开的最多文件数。然后使用一个循环,守护程序可以关闭所有可能的文件描述符。你必须决定你需要做这个或不做。如果你认为有可能有打开的文件描述 符,你需要关闭它们,因为系统有一个同时打开文件数的限制。 
7. 为标准输入,标准输出和标准错误输出建立新的文件描述符。即使你不打算使用它们,打开着它们不失为一个好主意。准确操作这些描述符是基于各自爱好;比如 说,如果你有一个日志文件,你可能希望把它作为标准输出和标准错误输出打开,而把‘/dev/null’作为标准输入打开;作为替代方法,你可以将‘ /dev/console’作为标准错误输出和/或标准输出打开,而‘/dev/null’作为标准输入,或者任何其它对你的守护程序有意义的结合方法。 (译者注:一般使用dup2函数原子化关闭和复制文件描述符。
--

def daemonize(stdout='/dev/null', stderr=None, stdin='/dev/null',  
              pidfile=None, startmsg = 'started with pid %s' ):  
    ''''' 
         This forks the current process into a daemon. 
         The stdin, stdout, and stderr arguments are file names that 
         will be opened and be used to replace the standard file descriptors 
         in sys.stdin, sys.stdout, and sys.stderr. 
         These arguments are optional and default to /dev/null. 
        Note that stderr is opened unbuffered, so 
        if it shares a file with stdout then interleaved output 
         may not appear in the order that you expect. 
     '''  
    # flush io  
    sys.stdout.flush()  
    sys.stderr.flush()  
    # Do first fork.  
    try:  
        pid = os.fork()  
        if pid > 0: sys.exit(0) # Exit first parent.  
    except OSError, e:  
        sys.stderr.write("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror))  
        sys.exit(1)         
    # Decouple from parent environment.  
    os.chdir("/")  
    os.umask(0)  
    os.setsid()  
    # Do second fork.  
    try:  
        pid = os.fork()  
        if pid > 0: sys.exit(0) # Exit second parent.  
    except OSError, e:  
        sys.stderr.write("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror))  
        sys.exit(1)  
    # Open file descriptors and print start message  
    if not stderr: stderr = stdout  
        si = file(stdin, 'r')  
        so = file(stdout, 'a+')  
        se = file(stderr, 'a+', 0)  #unbuffered  
        pid = str(os.getpid())  
        sys.stderr.write("\n%s\n" % startmsg % pid)  
        sys.stderr.flush()  
    if pidfile: file(pidfile,'w+').write("%s\n" % pid)  
    # Redirect standard file descriptors.  
    os.dup2(si.fileno(), sys.stdin.fileno())  
    os.dup2(so.fileno(), sys.stdout.fileno())  
    os.dup2(se.fileno(), sys.stderr.fileno())  

父进程执行代码到os.fork()处时,会将自己整个拷贝一份(即子进程)这时候父进程os.fork()的返回值大于零(即子进程的PID), 子进程os.fork()的返回值等于零,父进程结束,子进程继续执行,这时候又遇到第二个os.fork(),如上次一样,原来的子进程变成了父进程, 又产生新的子进程,之后父进程就结束。这就能够说通第一次是避免process group leader,第二次是避免session group leader。子进程就变成了一个五终端,无会话的完全自我掌控的后台进程了。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值