免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 12491 | 回复: 8
打印 上一主题 下一主题

SIGHUP信号与控制终端 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-06-02 11:35 |只看该作者 |倒序浏览
unix中进程组织结构为 session 包含一个前台进程组及一个或多个后台进程组,一个进程组包含多个进程。
一个session可能会有一个session首进程,而一个session首进程可能会有一个控制终端。
一个进程组可能会有一个进程组首进程。进程组首进程的进程ID与该进程组ID相等。
这儿是可能会有,在一定情况之下是没有的。

与终端交互的进程是前台进程,否则便是后台进程

SIGHUP会在以下3种情况下被发送给相应的进程:
1、终端关闭时,该信号被发送到session首进程以及作为job提交的进程(即用 & 符号提交的进程)
2、session首进程退出时,该信号被发送到该session中的前台进程组中的每一个进程
3、若夫进程退出导致进程组成为孤儿进程组,且该进程组中有进程处于停止状态(收到SIGSTOP或SIGTSTP信号),该信号会被发送到该进程组中的每一个进程。

系统对SIGHUP信号的默认处理是终止收到该信号的进程。所以若程序中没有捕捉该信号,当收到该信号时,进程就会退出。

下面观察几种因终端关闭导致进程退出的情况,在这儿进程退出是因为收到了SIGHUP信号。login shell是session首进程。

首先写一个测试程序,代码如下:
#include <stdio.h>
#include <signal.h>
char **args;
void exithandle(int sig)
{
       printf("%s : sighup received\n",args[1]);
}
int main(int argc,char **argv)
{
       args=argv;
       signal(SIGHUP,exithandle);
       pause();
       return 0;
}
程序中捕捉SIGHUP信号后打印一条信息,pause()使程序暂停。
编译后的执行文件为sigtest

1、命令: sigtest front > tt.txt
     操作: 关闭终端
   结果: tt文件的内容为 front : sighup received
    原因:  sigtest是前台进程,终端关闭后,根据上面提到的第1种情况,
         login shell作为session首进程,会收到SIGHUP信号然后退出,
         根据第2种情况,sigtest作为前台进程,
         会收到login shell发出的SIGHUP信号。
2、命令:sigtest back > tt.txt &
     操作: 关闭终端
   结果: tt文件的内容为 back : sighup received
    原因:  sigtest是提交的job,根据上面提到的第1种情况,
         sigtest会收到SIGHUP信号
3、写一个shell,内容为
    sigtest &
     执行该shell
     操作: 关闭终端
   结果: ps -ef | grep sigtest 会看到该进程还在,tt文件为空
   原因: 执行该shell时,sigtest作为job提交,然后该shell退出,
         致使sigtest变成了孤儿进程,不再是当前session的job了,
         因此sigtest即不是session首进程也不是job,不会收到SIGHUP
             同时孤儿进程属于后台进程,因此login shell退出后不会发送SIGHUP
             给sigtest,因为它只将该信号发送给前台进程。
         第3条说过若进程组变成孤儿进程组的时候,若有进程处于停止状态,
         也会收到SIGHUP信号,但sigtest没有处于停止状态,
         所以不会收到SIGHUP信号  
4、nohup sigtest > tt
   操作: 关闭终端
  结果: tt文件为空
  原因:  nohup可以防止进程收到SIGHUP信号

至此,我们就清楚了何种情况下终端关闭后进程会退出,何种情况下不会退出。

要想终端关闭后进程不退出有以下几种方法,均为通过shell的方式:
1、 编写shell,内容如下
    trap "" SIGHUP  #该句的作用是屏蔽SIGHUP信号,trap可以屏蔽很多信号
    sigtest
2、nohup sigtest 可以直接在命令行执行,
  若想做完该操作后继续别的操作,  可以 nohup sigtest &
3、 编写shell,内容如下
   sigtest &
   其实任何将进程变为孤儿进程的方式都可以,包括fork后父进程马上退出

论坛徽章:
0
2 [报告]
发表于 2006-06-02 13:47 |只看该作者
帮顶一下,不错。

个人觉得如果你要编程实现的话,只要使得你的进程成为一个daemon就可以了。
所以一般的方法是fork两次,并且把两个的Partent都exit掉就可以了。

论坛徽章:
0
3 [报告]
发表于 2006-06-02 15:04 |只看该作者
我的帖子主要是说明在shell中进程与SIGHUP信号的关系,以及终端关闭后不同情况下进程的表现。
若要做daemon进程,还是要按照《unix环境高级编程》中的方法,用fork,退出父进程,setsid脱离控制终端,关闭文件描述符,重新定位标准输入、标准输出、标准错误到/dev/null 等几个步骤。第二次fork是防止进程再次获得控制终端,因此第二次fork是可选的。第一次fork是为调用setsid做准备的。因此关键的只有2步,setsid脱离控制终端,重新定位标准输入、标准输出、标准错误到/dev/null

论坛徽章:
0
4 [报告]
发表于 2006-06-02 15:09 |只看该作者
right

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
5 [报告]
发表于 2006-06-02 15:29 |只看该作者
够深入~

论坛徽章:
0
6 [报告]
发表于 2006-06-02 22:57 |只看该作者
要是3天前看到这个会激动死。
刚刚用nohup解决了这个问题

论坛徽章:
0
7 [报告]
发表于 2007-09-29 14:16 |只看该作者
终端关闭时,该信号被发送到session首进程以及作为job提交的进程(即用 & 符号提交的进程)

应该是:终端关闭时,驱动程序会发信号SIGHUP给session首进程也就是SHELL了,如果此终端是伪终端的从端,且主端关闭,则信号还会发给前台进程组。SHELL收到SIGHUP后,一般会发给同一session的前台后进程组。

2、session首进程退出时,该信号被发送到该session中的前台进程组中的每一个进程
3、若夫进程退出导致进程组成为孤儿进程组,且该进程组中有进程处于停止状态(收到SIGSTOP或SIGTSTP信号),该信号会被发送到该进程组中的每一个进程。

正确

论坛徽章:
0
8 [报告]
发表于 2008-06-14 23:58 |只看该作者
楼主所说的不太确切,shell退出时是否发SIGHUP得看shell的选项,而且有些shell根本就不发,
而且你的这些试验在不同系统上有不同的行为

论坛徽章:
0
9 [报告]
发表于 2011-06-13 21:39 |只看该作者
前台进程,终端关闭后
在这个环境下 GNU bash, version 3.2.25
进程会收到2次SIGHUP信号 ,一次为  bash 退出前bash发送, 一次为会话首进程bash退出后 kernel发送.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP