﻿<?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++博客-多媒体软件开发-随笔分类-linux</title><link>http://www.cppblog.com/powervv/category/7492.html</link><description>记录自己的技术与生活点滴</description><language>zh-cn</language><lastBuildDate>Thu, 03 Jul 2008 17:13:40 GMT</lastBuildDate><pubDate>Thu, 03 Jul 2008 17:13:40 GMT</pubDate><ttl>60</ttl><item><title>Unix信号处理学习笔记</title><link>http://www.cppblog.com/powervv/archive/2008/06/30/54934.html</link><dc:creator>powervv</dc:creator><author>powervv</author><pubDate>Mon, 30 Jun 2008 01:19:00 GMT</pubDate><guid>http://www.cppblog.com/powervv/archive/2008/06/30/54934.html</guid><wfw:comment>http://www.cppblog.com/powervv/comments/54934.html</wfw:comment><comments>http://www.cppblog.com/powervv/archive/2008/06/30/54934.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/powervv/comments/commentRss/54934.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/powervv/services/trackbacks/54934.html</trackback:ping><description><![CDATA[<p><span>信号是传送给进程的一种事件通知，生成信号的事件有三大类：</span></p>
<p><span><span>1.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>程序错误：除零，非法内存访问</span><span>&#8230;</span></p>
<p><span><span>2.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>外部信号：终端</span><span>Ctrl-C</span><span>产生</span><span>SGINT</span><span>信号，定时器到期产生</span><span>SIGALRM&#8230;</span></p>
<p><span><span>3.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>显示请求：</span><span>kill</span><span>函数允许进程发送任何信号给其他进程或进程组。</span></p>
<p><span>信号生成既可以是同步的（信号与程序中的某个具体操作相关并在那个操作同时产生），也可以是异步的。通常程序错误生成信号为同步的，进程显式请求给自己的信号也是同步的。</span></p>
<p><span>外部事件总是异步的，来自其他进程的显示请求也是异步的。</span></p>
<p><span>信号发生时，我们可以告诉</span><span>unix</span><span>内核采取下面三种动作中的任一种：</span></p>
<p><span><span>1.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>忽略信号：大部分信号可被忽略，除</span><span>SIGSTOP</span><span>和</span><span>SIGKILL</span><span>信号外（这是超级用户杀掉或停掉任意进程的手段）。</span></p>
<p><span><span>2.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>捕获信号：注册信号处理函数，它对产生的特定信号做处理。</span></p>
<p><span><span>3.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>让信号默认动作起作用：</span><span>unix</span><span>内核定义的默认动作，有</span><span>5</span><span>种情况：</span></p>
<p><span><span>a)<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>流产</span><span>abort</span><span>：终止进程并产生</span><span>core</span><span>文件。</span></p>
<p><span><span>b)<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>终止</span><span>stop</span><span>：终止进程但不生成</span><span>core</span><span>文件。</span></p>
<p><span><span>c)<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>忽略：忽略信号。</span></p>
<p><span><span>d)<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>挂起</span><span>suspend</span><span>：挂起进程。</span></p>
<p><span><span>e)<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>继续</span><span>continue</span><span>：若进程是挂起的，则</span><span>resume</span><span>进程，否则忽略此信号。</span></p>
<p><span>任意时刻，进程可以为信号指定动作。</span></p>
<p><span>信号处理涉及两个过程，生成与交付。</span></p>
<p><span>信号生成出现在事件发生时，此时内核检查接收进程的相关数据结构，此结构中记录了信号的布局，悬挂信号集和处理动作。如果信号是要被忽略的，内核不做任何动作就返回。否则，将此信号加入悬挂信号集合中。（悬挂信号集合通常用位串表示，每位对应一个信号，内核无法记录同一信号的多个实例）。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>如果进程处于可中断的睡眠状态，并且该信号非阻塞，内核唤醒进程。被唤醒进程一旦运行则在返回用户态前优先处理悬挂信号，当有悬挂信号并且非阻塞时，内核查看是否有处理句柄，如果没有注册句柄，则采取默认动作（通常为终止进程）。如果有句柄，则将此信号加入阻塞信号屏蔽中。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>最后内核安排进程返回到用户态并执行信号句柄，同时保证句柄执行完时，进程从被中断处代码执行。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>由异步事件产生的信号可能在任一条指令后发生，当信号句柄完成时，进程从中断之处起执行。如果信号是在进程处于系统调用期间到达的，内核通常</span><span>abort</span><span>此系统调用并返回错误码</span><span>EINTR</span><span>。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>进程可以有选择的阻塞信号交付，当一个被阻塞的信号生成时，如果进程指定的动作为默认或者捕获，则此信号一直悬挂于该进程直到对此信号的阻塞放开，或者信号动作改为忽略。</span> <span>系统对阻塞信号的判定是在信号交付时而非生成时，这样可以允许进程在信号被交付前改变信号动作。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>每个进程有一个阻塞信号屏蔽，它定义当前被阻塞交付的那些信号。可认为它是一个位串，每位对应一个信号。如果某信号对应的位被设置，则该信号当前阻塞，进程可调用</span></p>
<p><span>sigprocmask</span><span>函数来检查或设置屏蔽。</span></p>
<p><span><br clear=all></span>&nbsp;</p>
<p><span>程序错误类信号：默认动作使进程流产，产生</span><span>core</span><span>文件。</span></p>
<p><span>SIGABRT</span><span>：</span><span><span>&nbsp;&nbsp; </span></span><span>调用</span><span>abort</span><span>函数生成的信号。</span></p>
<p><span>SIGFPE</span><span>：</span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>浮点计算错误。</span></p>
<p><span>SIGILL</span><span>：</span><span> <span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>非法指令错误。</span></p>
<p><span>SIGBUS/SIGSEGV</span><span>：</span><span> </span><span>硬件错误</span><span>-</span><span>非法地址访问。</span></p>
<p><span>SIGEMT</span><span>：</span><span> <span>&nbsp;&nbsp; </span></span><span>硬件错误</span></p>
<p><span>SIGSYS: <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>非法系统调用。</span></p>
<p><span>SIGTRAP</span><span>：</span><span><span>&nbsp;&nbsp; </span></span><span>硬件错误（通常为断点指令）。</span></p>
<p>&nbsp;</p>
<p><span>程序终止类信号：默认动作使进程终止，我们通常要处理这类信号，做一些清理工作，句柄函数应在结束时为此信号指定默认动作，然后再次生成该信号，使得程序终止。</span></p>
<p><span>SIGHUP</span><span>：终端断开连接时，生成此信号给控制进程。</span></p>
<p><span>SIGINT</span><span>：</span><span>Ctrl-C</span><span>或</span><span>Delete</span><span>按下时，由终端驱动生成，并发送给前台进程组中的所有进程。</span></p>
<p><span>SIGKILL</span><span>：使程序立即终止，不能被捕获或忽略，也不能被阻塞。</span></p>
<p><span>SIGQUIT</span><span>：</span><span>Ctrl-\,</span><span>如</span><span>SIGINT</span><span>，并且产生</span><span>core</span><span>。</span></p>
<p><span>SIGTERM</span><span>：该信号使程序终止，但是可以阻塞、捕获、忽略。</span></p>
<p>&nbsp;</p>
<p><span>闹钟类信号：通知定时器到期，默认动作是终止程序，但通常会设置句柄。</span></p>
<p><span>SIGALRM</span><span>：</span><span>alarm/setitimer</span><span>函数设置定时到期后，会产生此信号。</span></p>
<p><span>SIGPROF</span><span>：</span></p>
<p><span>SIGVTALRM</span><span>：</span></p>
<p>&nbsp;</p>
<p><span>I/O</span><span>类信号：通知进程在描述字上发生了感兴趣事件，支持信号驱动</span><span>IO</span><span>。</span></p>
<p><span>SIGIO</span><span>：</span><span><span> </span>fd</span><span>准备执行输入输出时发送此信号。</span></p>
<p><span>SIGPOLL</span><span>：异步</span><span>I/O</span><span>信号。</span></p>
<p><span>SIGURG</span><span>：网络收到带外数据时可选择生成此信号。</span></p>
<p>&nbsp;</p>
<p><span>作业控制类信号：</span></p>
<p><span>SIGCHLD</span><span>：</span><span><span>&nbsp;&nbsp; </span></span><span>进程终止或停止时会向其父进程发送该信号，默认动作为忽略。</span></p>
<p><span>SIGCONT:<span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>使停止的进程恢复运行。</span></p>
<p><span>SIGSTOP:<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>停止进程。</span></p>
<p><span>SIGTSTP/SIGTTIN/SIGTTOU:</span></p>
<p>&nbsp;</p>
<p><span>操作错误类信号：默认动作终止程序。</span></p>
<p><span>SIGPIPE</span><span>：</span><span><span>&nbsp;&nbsp;&nbsp; </span></span><span>管道破裂。</span></p>
<p><span>SIGXCPU/SIGXFSZ</span><span>：</span></p>
<p>&nbsp;</p>
<p><span>signal</span><span>函数：</span></p>
<p><span>void (* signal(int sig, void (*func)(int)))(int);</span></p>
<p><span>sig</span><span>指明是哪一种信号。</span></p>
<p><span>func</span><span>指明动作：</span><span>SIG_DFL</span><span>，</span><span> SIG_IGN</span><span>，或者信号句柄地址。</span></p>
<p><span>当信号发生时，如果</span><span>func</span><span>指向信号句柄，系统在将控制转往句柄前，先将该信号动作置为</span><span>DFL,</span><span>或者阻塞该信号直到句柄完成。</span></p>
<p><span>Signal</span><span>函数返回值指向前一次有效动作指针：</span><span>SIG_DFL,SIG_IGN,</span><span>或信号地址，这提供了恢复信号动作的机制。</span> <span>如果</span><span>signal</span><span>调用出错，返回</span><span>SIG_ERR</span><span>并设置</span><span>errno</span><span>。</span></p>
<p>&nbsp;</p>
<p><span>进程初启时的信号动作：</span></p>
<p><span>fork:</span><span>继承父进程的动作</span></p>
<p><span>exec:</span><span>所有信号动作要么是忽略要么是默认。</span></p>
<p>&nbsp;</p>
<p><span>不可靠信号：</span></p>
<p><span>早期版本</span><span>Unix</span><span>中使用</span><span>signal</span><span>，每当信号交付时，其动作总是由系统重置为默认动作，因此为了使信号句柄执行期间，仍能对同一信号后续做反应，需要再次调用</span><span>signal</span><span>。</span></p>
<p><span>Catch_Signal(){</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>// </span><span>如果第二次信号刚好在此时发生，将导致进程终止</span><span>core</span><span>掉。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>signal(SIGQUIT,Catch_Signal);</span></p>
<p><span>}</span></p>
<p><span>Main(){<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>signal(SIGQUIT, Catch_Signal);</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&#8230;</span></p>
<p><span>}</span></p>
<p><span>使用</span><span>signal</span><span>的另一个问题是，对于信号，进程要么忽略，要么捕获，无法在一段时间内阻塞信号（推迟信号的交付），为了克服</span><span>signal</span><span>兼容性问题，现代</span><span>unix</span><span>均实现了</span><span>POSIX</span><span>定义的</span><span>sigaction</span><span>函数，该函数采用一个</span><span>sigaction</span><span>结构，除定义信号交付时要采取的动作外，还包含其他一些动作控制信息。</span></p>
<p><span>sigaction</span><span>还允许调用进程检测或指定与特定信号相关的动作。</span></p>
<p><span>int sigaction(int sig, const struct sigaction* act, struct sigaction* oact);</span></p>
<p><span>sig</span><span>指定信号</span><span>-</span><span>除</span><span>SIGKILL</span><span>和</span><span>SIGSTOP</span><span>。</span></p>
<p><span>如果</span><span>act</span><span>为</span><span>NULL</span><span>，则不改变信号动作，只查询当前动作。</span></p>
<p><span>成功返回</span><span>0</span><span>，失败则不安装新信号动作，返回</span><span>-1</span><span>，设置</span><span>errno</span><span>。</span></p>
<p><span>struct sigaction{</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>void </span><span>（</span><span>*sa_handler</span><span>）</span><span>(int);<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>// </span><span>同</span><span>signal</span><span>的第二参数</span><span>func</span><span>。</span><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>void<span> </span>(*sa_sigaction)(int, siginfo_t*, void*); // </span><span>仅当</span><span>flags</span><span>设置</span><span>SA_SIGINFO</span><span>起作用。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>sigset_t sa_mask;<span>&nbsp;&nbsp;&nbsp; </span>// </span><span>指明信号执行期间要阻塞的一组信号，除此之外导致信号句柄执</span></p>
<p><span>行的信号也自动阻塞，除非指定了</span><span>SA_NODEFER</span><span>。信号句柄正常返回时，屏蔽恢复到原先状态。</span><span><span>&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>int sa_flags;<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>// </span></p>
<p><span>}</span><span>；</span></p>
<p><span>sa_flags</span><span>是一个位串，可以通过或运算生成。可设置下列标志：</span></p>
<p><span>SA_NOCLDSTOP: </span><span>只对</span><span>CHLD</span><span>信号起作用，子进程暂停时不发信号给父进程。</span></p>
<p><span>SA_RESTART: </span><span>信号句柄返回时，自动恢复被该信号中断的系统调用。否则该系统调用将中断返回</span><span>-1</span><span>，并设置</span><span>errno</span><span>为</span><span>EINTR</span><span>。</span></p>
<p><span>SA_ONSTACK:</span></p>
<p><span>SA_RESETHAND</span><span>：信号句柄入口，系统将重置信号动作为</span><span>SIG_DFL.</span></p>
<p><span>SA_NODEFER:</span><span>句柄执行期间，不自动阻塞该信号。</span></p>
<p><span>SA_NOCLDWAIT:</span><span>只对</span><span>CHLD</span><span>起作用，调用进程的所有子进程在终止时不会成为</span><span>Zombe</span><span>。这种情况下，父进程无需要</span><span>wait</span><span>子进程，并且子进程终止也不向父进程发</span><span>SIGCHLD</span><span>信号。</span></p>
<p><span>如果父进程调用</span><span>wait</span><span>，将阻塞到所有子进程终止，并返回</span><span>-1</span><span>，</span><span>errno</span><span>设为</span><span>ECHILD.</span></p>
<p><span>SA_SIGINFO:</span><span>如果未设置此标志，则信号句柄原型为：</span></p>
<p><span>&nbsp;void func(int signo);</span></p>
<p><span>如果设置此标志，则句柄原型为：</span></p>
<p><span>void func(int signo, singinfo_t* info, void* context);</span></p>
<p><span>Info- </span><span>解释信号生成的原因。</span></p>
<p><span>Context-</span><span>信号被交付时所中断进程的上下文。</span></p>
<p><span>一旦用</span><span>sigaction</span><span>为特定信号建立了动作，该动作就一直保持，直到另一次调用</span><span>sigaction</span><span>，或者调用</span><span>exec</span><span>，或者因设置了</span><span>SA_RESETHAND</span><span>导致系统自动改变动作为默认为止。</span></p>
<p>&nbsp;</p>
<p><span>除了外部中断产生信号外，程序可以显式的调用</span><span>raise</span><span>函数给他自己发送信号，或调用</span><span>kill</span><span>向自己或其他进程发送信号。</span></p>
<p>&nbsp;</p>
<p><span>阻塞信号意味着保持该信号并推迟它的交付，可以防止程序中的关键代码被信号中断。</span></p>
<p><span>信号集操作：</span></p>
<p><span>int sigemptyset(sigset_t* set); // </span><span>清空信号集</span></p>
<p><span>int sigfillset(sigset_t* set);<span>&nbsp;&nbsp; </span>// </span><span>包含所有信号集</span></p>
<p><span>sigaddset/sigdelset/sigismember;</span></p>
<p><span>sigprocmask</span><span>用来检测或改变调用进程的信号屏蔽。</span></p>
<p><span>int sigprocmask(int how, const sigset_t* set, sigset_t* oset);</span></p>
<p><span>How: SIGBLOCK&nbsp;SIG_UNBLOCK<span>&nbsp;&nbsp; </span>SIG_SETMASK</span></p>
<p><span>如果调用</span><span>sigprocmask</span><span>放开某个信号而导致任何悬挂信号被解除阻塞，则函数返回前，这些信号中至少有一个被交付。</span></p>
<p><span>检查悬挂信号：</span><span>int sigpending(sigset_t* set);</span></p>
<p><span>等待信号：</span><span>int pause(void); </span></p>
<p><span>悬挂调用进程直到有一个信号到达。仅当句柄执行并返回时，</span><span>pause</span><span>函数才返回：此时返回</span><span>-1</span><span>，并设置</span><span>errno</span><span>为</span><span>EINTR</span><span>。所有其他情况下</span><span>pause</span><span>不返回。</span></p>
<p>&nbsp;</p>
<p><span>如果多个相同信号在信号句柄运行前发给了进程，则句柄只被运行一次。换句话说，默认情况下</span><span>unix</span><span>信号是非排队的，只有当实现支持实时信号并且</span><span>sa_flags</span><span>设置</span><span>SA_SIGINFO</span><span>时，由</span><span>sigqueue</span><span>生成的后续信号才排队。</span></p>
<p>&nbsp;</p>
<p><span>I/O</span><span>执行期间，有可能到达信号，此时有两种情况：重新开始系统调用还是返回失败</span><span>.</span></p>
<p><span>早期</span><span>unix</span><span>特征为，进程执行慢系统调用期间捕获信号时，该调用被中断并设置</span><span>errno</span><span>为</span><span>EINTR</span><span>。现代</span><span>unix</span><span>增加了</span><span>sa_flags</span><span>选项</span><span>SA_RESTART</span><span>可对单个信号要求自动恢复被中断的系统调用。</span></p>
<p><span>原则如下：如果进程阻塞于慢系统调用，并且进程捕获信号且该信号句柄返回，系统调用可能返回</span><span>EINTR</span><span>。</span> <span>虽然有些</span><span>unix</span><span>能自动恢复系统调用，但是为了兼容性，我们必须准备慢系统调用返回</span><span>EINTR</span><span>，当检测到</span><span>EINTR</span><span>，要么重新开始系统调用，要么做其他处理。</span></p>
<p><span>Again</span><span>：</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if (n=read(fd,buff, BUFSIZE) &lt; 0) {</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if (errno ==EINTR)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>goto Again;</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>else</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&#8230;}</span></p>
<img src ="http://www.cppblog.com/powervv/aggbug/54934.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/powervv/" target="_blank">powervv</a> 2008-06-30 09:19 <a href="http://www.cppblog.com/powervv/archive/2008/06/30/54934.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>