创建守护进程为什么fork两次
来源:互联网 发布:rtsp协议端口 编辑:程序博客网 时间:2024/06/06 16:50
守护进程(daemon进程)是后台守护进程,有时候也叫精灵进程(agent).Linux 下server都是daemon进程。
其特点是:
1)其父进程是一号进程,通常以d结尾
2)在后台运行,独立于终端,周期性的以某种任务或等待处理某些发生的事
3)自成进程组,自成会话,不受登陆注销等影响
4)一般是孤儿进程
daemon函数存在的原因是因为控制终端由于某些原因(如断开终端链接)会发送一些信号的原因。而接收进程处理这些信号缺省动作会让进程退出。这些信号会由于终端上敲一些特殊按键而产生。
创建守护进程最关键的⼀一步是调⽤用setsid函数创建⼀一个新的Session,并成为Session Leader。
该函数调⽤用成功时返回新创建的Session的id(其实也就是当前进程的id),出错返回-1。注意,调 ⽤用这个函数之前,当前进程不允许是进程组的Leader,否则该函数返回-1。要保证当前进程不 是进 程组的Leader也很容易,只要先fork再调⽤用setsid就⾏行了。fork创建的⼦子进程和⽗父进程在同 ⼀一个进 程组中,进程组的Leader必然是该组的第⼀一个进程,所以⼦子进程不可能是该组的第⼀一个 进程,在⼦子 进程中调⽤用setsid就不会有问题了。
成功调⽤用该函数的结果是:
1. 创建⼀一个新的Session,当前进程成为Session Leader,当前进程的id就是Session的id。
2. 创建⼀一个新的进程组,当前进程成为进程组的Leader,当前进程的id就是进程组的id。
3. 如果当前进程原本有⼀一个控制终端,则它失去这个控制终端,成为⼀一个没有控制终端的进 程。所谓失去控制终端是指,原来的控制终端仍然是打开的,仍然可以读写,但只是⼀一个普 通的打开⽂文件⽽而不是控制终端了。
创建守护进程
1. 调⽤用umask将⽂文件模式创建屏蔽字设置为0.
2. 调⽤用fork,⽗父进程退出(exit)。原因:1)如果该守护进程是作为⼀一条简单的shell命令 启动的,那么⽗父进程终⽌止使得shell认为该命令已经执⾏行完毕。2)保证⼦子进程不是⼀一个 进程组的组长进程。
3. 调⽤用setsid创建⼀一个新会话。setsid会导致:1)调⽤用进程成为新会话的⾸首进程。 2)调⽤用 进程成为⼀一个进程组的组长进程 。3)调⽤用进程没有控制终端。(再次fork⼀一次,保证 daemon进程,之后不会打开tty设备)
4. 将当前⼯工作⽬目录更改为根⽬目录。
5. 关闭不在需要的⽂文件描述符。
6. 其他:忽略SIGCHLD信号
贴一个daemon函数常见的实现:
1 、第一次fork的作用是让shell 认为本条命令 已经终止,不用挂在终端输入上。还有一个作用是为后面setsid服务。setsid的调用者不能是进程组组长(group leader). 此时父进程是进程组组长。
2 、setsid() 是本函数最重要的一个调用。它完成了daemon函数想要做的大部分事情。调用完整个函数。子进程是会话组长(sid==pid),也是进程组组长(pgid == pid),并且脱离了原来控制终端。到了这一步,基本上不管控制终端如何怎么样。新的进程都不会收到那些信号。
3 、经过前面2个步骤,基本想要做的都做了。第2次fork不是必须的。也看到很多开源服务没有fork第二次。fork第二次主要目的是。防止进程再次打开一个控制终端。因为打开一个控制终端的前台条件是该进程必须是会话组长。再fork一次,子进程ID != sid(sid是进程父进程的sid)。所以也无法打开新的控制终端。
daemon目的就是防止终端产生的一些信号让进程退出。上面函数并没有直接调用signal函数去处理它。而是间接通过fork和setsid函数使用更少代码优雅处理。而被有些人误以为是僵死进程的原因需要这样处理。
当然,也有很多程序不是像上面函数那样去实现。而是直接通过忽略信号方式处理。这样其实也不错,因为这些信号很少会有用到的价值。直接忽略基本上不存在误杀的情况。反正达到最终目的就可以。条条大路通罗马。
下面罗列一下控制终端会产生哪些信号。程序中只要处理好这些信号,同样能达到上面函数实现的目的。
//后台进程读取/写入终端输入产生下面两个信号,或者控制终端不存在情况读取和写入会产生
signal(SIGTTOU, SIG_IGN);
signal(SIGTTIN, SIG_IGN);
//按CTRL-C ,CTRL-\ CTRL-Z会向前台进程组发送下面这些信号
signal(SIGINT, SIG_IGN );
signal(SIGQUIT, SIG_IGN );
signal(SIGTSTP, SIG_IGN );
//终端断开,会给会话组长或孤儿进程组所有成员发送下面信号
signal(SIGHUP, SIG_IGN );
还有有些信号也可以由终端shell产生,需要关注
signal(SIGCONT, SIG_IGN );
signal(SIGSTOP, SIG_IGN );
上面这些信号,应该有些程序缺省处理(SIG_DFL)本身动作就是忽略(SIG_IGN),不是退出进程。不过按照上面写也不会造成什么问题
- 创建守护进程为什么fork两次
- 创建守护进程为什么fork两次
- 创建守护进程以及为什么fork两次
- 创建守护进程为什么要fork两次
- 为什么守护进程要fork()两次
- 守护进程为什么要fork两次?
- Linux--守护进程,为什么要fork两次
- 创建守护进程为什仫要fork两次
- 创建守护进程为何fork两次
- 创建守护进程fork一次与fork两次的区别
- Android守护进程--为什么要fork()两次
- Linux(十二):守护进程为什么fork两次?
- 守护进程 & 创建守护进程 & fork一次和fork两次的区别
- 守护进程 & 创建守护进程 & fork一次和fork两次的区别
- 守护进程&创建守护进程&fork一次和fork两次的区别
- 守护进程Daemon---fork两次
- 详解守护进程的创建与fork两次分析
- 创建进程时,为什么fork会返回两次?
- 杭电2001题
- HDU 2051 JAVA
- 单播、多播(组播)和广播的区别
- 新人报道
- sdutacm-AOE网上的关键路径
- 创建守护进程为什么fork两次
- 一位资深程序员大牛给予Java初学者的学习路线建议
- 无线网络转为有线网络
- 推荐5个值得学习React Native的开源项目
- Adam:大规模分布式机器学习框架
- 如何用自己电脑做服务器,绑定域名建一个个人网站
- ionic 轮播用ng-repeat遍历后不显示问题
- 1179: [Apio2009]Atm
- bzoj1631