﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-&lt;font style="position:absolute; top:10px; left:20px; color: #c0c0c0;  "&gt;幽幽&lt;/font&gt;-随笔分类-Linux</title><link>http://www.cppblog.com/justin-shi/category/6155.html</link><description>&lt;font&gt;&amp;nbsp;&lt;/font&gt;   </description><language>zh-cn</language><lastBuildDate>Tue, 14 Oct 2014 15:37:50 GMT</lastBuildDate><pubDate>Tue, 14 Oct 2014 15:37:50 GMT</pubDate><ttl>60</ttl><item><title>daemon 进程为什么要fork两次</title><link>http://www.cppblog.com/justin-shi/archive/2014/10/10/208530.html</link><dc:creator>幽幽</dc:creator><author>幽幽</author><pubDate>Fri, 10 Oct 2014 06:15:00 GMT</pubDate><guid>http://www.cppblog.com/justin-shi/archive/2014/10/10/208530.html</guid><wfw:comment>http://www.cppblog.com/justin-shi/comments/208530.html</wfw:comment><comments>http://www.cppblog.com/justin-shi/archive/2014/10/10/208530.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/justin-shi/comments/commentRss/208530.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/justin-shi/services/trackbacks/208530.html</trackback:ping><description><![CDATA[<span style="color: #666666; font-family: 宋体, Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;">&nbsp; daemon进程是后台守护进程，有时候也叫精灵进程(agent).linux 下server都是daemon进程。相信大部分开发人员都知道如何去写一个daemon进程。但是另一方面，大部分人不知道为什么要这么做，不少人是从某个地方copy一个函数，拿来主义。但是具体为什么这么实现，却不是很透彻。</span>
<div style="word-wrap: break-word; color: #666666; font-family: 宋体, Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;"></div>
<div style="word-wrap: break-word; color: #666666; font-family: 宋体, Arial; font-size: 16px; line-height: 26px; background-color: #ffffff;">&nbsp; 见过一些面试官或被面试人。很多人解释daemon进程存在的理由是因为僵死进程。或者输入输出。其实和这些东西一毛钱关系都没有。daemon函数存在的原因是因为控制终端由于某些原因（如断开终端链接）会发送一些信号的原因。而接收进城处理这些信号缺省动作会让进程退出。这些信号会由于终端上敲一些特殊按键而产生。<br style="word-wrap: break-word;" />
<div style="word-wrap: break-word;"><br />
</div>
<div style="word-wrap: break-word;">&nbsp; 贴一个daemon函数常见的实现:<br />
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;daemon(</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">)<br />
</span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; ">{<br />
</span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;pid_t&nbsp;pid&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;fork();<br />
</span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; "><br />
</span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(&nbsp;pid&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;)&nbsp;exit(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">);</span><span style="color: #008000; ">//</span><span style="color: #008000; ">parent<br />
</span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #008000; "><br />
</span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">first&nbsp;children</span><span style="color: #008000; "><br />
</span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(setsid()&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)<br />
</span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">setsid&nbsp;failed\n</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />
</span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assert(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br />
</span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">);<br />
</span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #000000; "><br />
</span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;umask(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br />
</span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #000000; "><br />
</span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #000000; "><br />
</span><span style="color: #008080; ">18</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;pid&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;fork();<br />
</span><span style="color: #008080; ">19</span>&nbsp;<span style="color: #000000; "><br />
</span><span style="color: #008080; ">20</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(&nbsp;pid&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;exit(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br />
</span><span style="color: #008080; ">21</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;<br />
</span><span style="color: #008080; ">22</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">second&nbsp;children&nbsp;</span><span style="color: #008000; "><br />
</span><span style="color: #008080; ">23</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;chdir&nbsp;(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">/</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />
</span><span style="color: #008080; ">24</span>&nbsp;<span style="color: #000000; "><br />
</span><span style="color: #008080; ">25</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;i&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;&nbsp;i&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">3</span><span style="color: #000000; ">;&nbsp;i</span><span style="color: #000000; ">++</span><span style="color: #000000; ">)<br />
</span><span style="color: #008080; ">26</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080; ">27</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close&nbsp;(i);<br />
</span><span style="color: #008080; ">28</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080; ">29</span>&nbsp;<span style="color: #000000; "><br />
</span><span style="color: #008080; ">30</span>&nbsp;<span style="color: #000000; "><br />
</span><span style="color: #008080; ">31</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;stdfd&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;open&nbsp;(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">/dev/null</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;O_RDWR);<br />
</span><span style="color: #008080; ">32</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;dup2(stdfd,&nbsp;STDOUT_FILENO);<br />
</span><span style="color: #008080; ">33</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;dup2(stdfd,&nbsp;STDERR_FILENO);<br />
</span><span style="color: #008080; ">34</span>&nbsp;<span style="color: #000000; "><br />
</span><span style="color: #008080; ">35</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br />
</span><span style="color: #008080; ">36</span>&nbsp;<span style="color: #000000; ">}<br />
</span><span style="color: #008080; ">37</span>&nbsp;<br />
<span style="color: #000000; "></span></div>
</div>
</div><br /><div style="word-wrap: break-word; font-size: 16px;"><div style="word-wrap: break-word;"><div style="word-wrap: break-word;">&nbsp; &nbsp; 1 、第一次fork的作用是让shell 认为本条命令 已经终止，不用挂在终端输入上。还有一个作用是为后面setsid服务。setsid的调用者不能是进程组组长(group leader). 此时父进程是进程组组长。</div><div style="word-wrap: break-word;">&nbsp; &nbsp;&nbsp;</div><div style="word-wrap: break-word;">&nbsp; &nbsp; 2 、setsid() 是本函数最重要的一个调用。它完成了daemon函数想要做的大部分事情。调用完整个函数。子进程是会话组长(sid==pid)，也是进程组组长(pgid == pid)，并且脱离了原来控制终端。到了这一步，基本上不管控制终端如何怎么样。新的进程都不会收到那些信号。</div><div style="word-wrap: break-word;"></div><div style="word-wrap: break-word;">&nbsp; &nbsp; 3 &nbsp;、经过前面2个步骤，基本想要做的都做了。第2次fork不是必须的。也看到很多开源服务没有fork第二次。fork第二次主要目的是。防止进程再次打开一个控制终端。因为打开一个控制终端的前台条件是该进程必须是会话组长。再fork一次，子进程ID != sid（sid是进程父进程的sid）。所以也无法打开新的控制终端。</div><div style="word-wrap: break-word;"></div><div style="word-wrap: break-word;">&nbsp; &nbsp; daemon目的就是防止终端产生的一些信号让进程退出。上面函数并没有直接调用signal函数去处理它。而是间接通过fork和setsid函数使用更少代码优雅处理。而被有些人误以为是僵死进程的原因需要这样处理。</div><div style="word-wrap: break-word;"></div><div style="word-wrap: break-word;">&nbsp; &nbsp; 当然，也有很多程序不是像上面函数那样去实现。而是直接通过忽略信号方式处理。这样其实也不错，因为这些信号很少会有用到的价值。直接忽略基本上不存在误杀的情况。反正达到最终目的就可以。条条大路通罗马。</div><div style="word-wrap: break-word;"></div><div style="word-wrap: break-word;">&nbsp; &nbsp;下面罗列一下控制终端会产生哪些信号。程序中只要处理好这些信号，同样能达到上面函数实现的目的。</div><div style="word-wrap: break-word;"></div><div style="word-wrap: break-word;">&nbsp; &nbsp;//后台进程读取/写入终端输入产生下面两个信号，或者控制终端不存在情况读取和写入会产生</div><div style="word-wrap: break-word;">&nbsp; &nbsp;signal(SIGTTOU, SIG_IGN);</div><div style="word-wrap: break-word;">&nbsp; &nbsp;signal(SIGTTIN, SIG_IGN);</div><div style="word-wrap: break-word;"></div><div style="word-wrap: break-word;">&nbsp; &nbsp;//按CTRL-C ,CTRL-\ CTRL-Z会向前台进程组发送下面这些信号</div><div style="word-wrap: break-word;">&nbsp; &nbsp;signal(SIGINT, &nbsp;SIG_IGN );</div><div style="word-wrap: break-word;">&nbsp; &nbsp;signal(SIGQUIT, SIG_IGN );</div><div style="word-wrap: break-word;">&nbsp; &nbsp;signal(SIGTSTP, SIG_IGN );</div><div style="word-wrap: break-word;">&nbsp; &nbsp;</div><div style="word-wrap: break-word;">&nbsp; &nbsp;//终端断开，会给会话组长或孤儿进程组所有成员发送下面信号</div><div style="word-wrap: break-word;">&nbsp; &nbsp;signal(SIGHUP, &nbsp;SIG_IGN );</div><div style="word-wrap: break-word;"></div><div style="word-wrap: break-word;">&nbsp; &nbsp;还有有些信号也可以由终端shell产生，需要关注</div><div style="word-wrap: break-word;">&nbsp; &nbsp;signal(SIGCONT, SIG_IGN );</div><div style="word-wrap: break-word;">&nbsp; &nbsp;signal(SIGSTOP, SIG_IGN );</div><div style="word-wrap: break-word;"></div><div style="word-wrap: break-word;"></div><div style="word-wrap: break-word;">&nbsp; 上面这些信号，应该有些程序缺省处理（SIG_DFL）本身动作就是忽略（SIG_IGN），不是退出进程。不过按照上面写也不会造成什么问题。</div></div></div><img src ="http://www.cppblog.com/justin-shi/aggbug/208530.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/justin-shi/" target="_blank">幽幽</a> 2014-10-10 14:15 <a href="http://www.cppblog.com/justin-shi/archive/2014/10/10/208530.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自己动手创建交叉工具链</title><link>http://www.cppblog.com/justin-shi/archive/2008/02/10/42622.html</link><dc:creator>幽幽</dc:creator><author>幽幽</author><pubDate>Sun, 10 Feb 2008 08:18:00 GMT</pubDate><guid>http://www.cppblog.com/justin-shi/archive/2008/02/10/42622.html</guid><wfw:comment>http://www.cppblog.com/justin-shi/comments/42622.html</wfw:comment><comments>http://www.cppblog.com/justin-shi/archive/2008/02/10/42622.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/justin-shi/comments/commentRss/42622.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/justin-shi/services/trackbacks/42622.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 首先，制作交叉工具链的目的是为了给我的手机--MOTO ROKR E2编译程序。然后，顺便学习一下嵌入式软件的开发先说一下，搞这个需要很大的耐心。我用的硬件是Sempron3100+, 512MB内存, 编译环境是windowsXP + vmware5.5 + gentoo, 在CUI下，花了大概20个小时才编译完（我从晚上八点一直弄到第二天下午四点）。1. 准备源码:&nbsp;binuitls...&nbsp;&nbsp;<a href='http://www.cppblog.com/justin-shi/archive/2008/02/10/42622.html'>阅读全文</a><img src ="http://www.cppblog.com/justin-shi/aggbug/42622.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/justin-shi/" target="_blank">幽幽</a> 2008-02-10 16:18 <a href="http://www.cppblog.com/justin-shi/archive/2008/02/10/42622.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>