当前位置: 技术问答>linux和unix
有关会话期跟控制终端的疑问
来源: 互联网 发布时间:2016-04-05
本文导语: 首先介绍一下我的环境,WMware + FC5, SecureCRT+SSH. 测试程序: int main() { pid_t pid; pid = fork(); if (pid == 0) { while(1) { //print pid, ppid, pgrpid; ...
首先介绍一下我的环境,WMware + FC5, SecureCRT+SSH.
测试程序:
对会话期的理解.我一直认为SSH上Linux后就会为这个连接创建一个会话期及相应的伪终端,当断开连接后这个会话期也就结束了。会话期结束时会给所有属于这个会话期的进程都发送信号,至使属于这个会话期的进程都退出,所以我们的程序如何从shell手动启动如果要使其在断开shell时仍然保持运行,需要做成daemon程序(最主要的就是新建会话期).
但是如上的测试程序我发现,直接运行不加&, 当父进程退出后,断开SSH连接使会话期结束上面子进程并不会退出,如果是这样的话,APUE书上做daemon程序的核心步骤setsid()是不是多余了呢?
更奇怪的是,当我加了&运行的话,断开SSH结束会话期,子进程却会跟着退出。加&与否跟这个子进程退出有什么关系?
另外,我昨天的一个帖子问为什么只要父进程退出后,子进程就捕捉不到终端产生的信号,你回答说是有无控制终端的原因,意思是这时终端控制权归shell了吧,但为什么我子进程的输出却还可以输到这个控制终端呢?控制终端跟终端有区别?
thanks in advance!
测试程序:
int main()
{
pid_t pid;
pid = fork();
if (pid == 0)
{
while(1)
{
//print pid, ppid, pgrpid;
sleep(2);
}
}
else if (pid > 0)
{
//print pid, ppid, pgrpid;
}
else
{
//fork error;
}
return 0;
}
对会话期的理解.我一直认为SSH上Linux后就会为这个连接创建一个会话期及相应的伪终端,当断开连接后这个会话期也就结束了。会话期结束时会给所有属于这个会话期的进程都发送信号,至使属于这个会话期的进程都退出,所以我们的程序如何从shell手动启动如果要使其在断开shell时仍然保持运行,需要做成daemon程序(最主要的就是新建会话期).
但是如上的测试程序我发现,直接运行不加&, 当父进程退出后,断开SSH连接使会话期结束上面子进程并不会退出,如果是这样的话,APUE书上做daemon程序的核心步骤setsid()是不是多余了呢?
更奇怪的是,当我加了&运行的话,断开SSH结束会话期,子进程却会跟着退出。加&与否跟这个子进程退出有什么关系?
另外,我昨天的一个帖子问为什么只要父进程退出后,子进程就捕捉不到终端产生的信号,你回答说是有无控制终端的原因,意思是这时终端控制权归shell了吧,但为什么我子进程的输出却还可以输到这个控制终端呢?控制终端跟终端有区别?
thanks in advance!
|
对。补充:还要断开控制终端,这也是setsid的功能之一。否则,ctrl+C可能就把daemon挂了。
至于33楼的总结,就不深究了,可能是实现有差别。搞清楚为什么会退出,也就搞清楚了nohup的作用,就可以了。
至于33楼的总结,就不深究了,可能是实现有差别。搞清楚为什么会退出,也就搞清楚了nohup的作用,就可以了。
|
操作系统原理上的东西我了解不多,帮顶。
刚查了setsid的man
[code=BatchFile]NOTES
A child created via fork(2) inherits its parent's session ID. The session
ID is preserved across an execve(2).
A process group leader is a process with process group ID equal to its PID.
In order to be sure that setsid() will succeed, fork() and exit(), and have
the child do setsid().[/code]
接着继续查session 的作用。
不过,感觉楼主所说的“会话期结束时会给所有属于这个会话期的进程都发送信号,至使属于这个会话期的进程都退出”是有问题的。
没有这样做的理由。
刚查了setsid的man
[code=BatchFile]NOTES
A child created via fork(2) inherits its parent's session ID. The session
ID is preserved across an execve(2).
A process group leader is a process with process group ID equal to its PID.
In order to be sure that setsid() will succeed, fork() and exit(), and have
the child do setsid().[/code]
接着继续查session 的作用。
不过,感觉楼主所说的“会话期结束时会给所有属于这个会话期的进程都发送信号,至使属于这个会话期的进程都退出”是有问题的。
没有这样做的理由。
|
我来说两句吧,这个问题情况很复杂,不同版本的Unix,不同的shell都不一样。比如我们曾经就有这样的情况:AIX的操作系统,当使用sh时,t1这样的程序在终端退出时会退出。但是使用ksh时,t1&这样的程序在终端退出时会保留。所以要看操作系统而定,但是最保险的做法就是使用setsid()。
向这种不同Unix版本不兼容的情况很多的,不支这一个,比如waitpid(或wait),可以返回退出子进程的ID号,所有的书和man中都是这门说的,但是你到SCO下试试,不管怎么样都不行。所以我建议你不要挖的太深了,“好读书,不求甚解”,只要能用就行了。你对会话期的理解应该是正确的。
另外关于后台进程可以写终端的问题,这个情况很简单,终端在linux中也是一个文件,比如在SCO下这个文件叫/etc/tty01或者/etc/tty1p等等之内的,你直接向那个文件中写东西,这些东西就自动显示到屏幕中去(前提是这个终端是打开的),因此输出是很容易的。
向这种不同Unix版本不兼容的情况很多的,不支这一个,比如waitpid(或wait),可以返回退出子进程的ID号,所有的书和man中都是这门说的,但是你到SCO下试试,不管怎么样都不行。所以我建议你不要挖的太深了,“好读书,不求甚解”,只要能用就行了。你对会话期的理解应该是正确的。
另外关于后台进程可以写终端的问题,这个情况很简单,终端在linux中也是一个文件,比如在SCO下这个文件叫/etc/tty01或者/etc/tty1p等等之内的,你直接向那个文件中写东西,这些东西就自动显示到屏幕中去(前提是这个终端是打开的),因此输出是很容易的。