Friday, July 24, 2009

系统下的Session

将会涉及到两个概念:
1. session
2. process group

总体关系如下:


Session

关于session的用处:
When a user logs out of a system, the kernel needs to terminate all the
processes the user had running (otherwise, users would leave a slew of
old processes sitting around waiting for input that can never arrive).
To simplify this task, processes are organized into sets of sessions. The session's ID is the same as the pid of the process that created the session through the setsid() system call. That process is known as the session leader
for that session group. All of that process's descendants are then
members of that session unless they specifically remove themselves from
it. The setsid() function does not take any arguments and returns the new session ID.


如下为ssh登陆后, 进程的PID树与session的情况:
会话信息:
$ ps axo user,pid,rgid,session,command | less
.... 截 ....
root     26323     0 26323 sshd: jessinio [priv]
jessinio 26331  1000 26323 sshd: jessinio@pts/0
jessinio 26332  1000 26332 -bash
jessinio 26349  1000 26332 less
jessinio 26357  1000 26332 python test_session.py
jessinio 26358  1000 26332 ps axo user,pid,rgid,session,command
jessinio 26359  1000 26332 less
.... 截 ....


进程树:
$ pstree -p
.... 截 ....
        |-sshd(2051)---sshd(26323)---sshd(26331)---bash(26332)-+-less(26349)
        |                                                                                          |-less(26477)
        |                                                                                          |-pstree(26476)
        |                                                                                          `-python(26357)
.... 截 ....
    
通过ssh登陆时, 是通过sshd运行bash(交互)的. 这时的bash自己成为session leader(这是交互性bash的特点, 并且使用自己的controlling terminal)
 * session被设置成与进程号一样的数字: 因为PID在系统中是唯一的.
 * 在进程不强制使用setsid系统调用的情况下, 是要继承父进程的session号的.
 * 使用setsid系统调用需要一定的要求: This is allowed only when the current process is not a process group leader.
 * 至以为什么sshd(蓝色部分)的第一个进程不退出来, 它的功能还是很有意思的: 至少父进程可以知道子进程的状态
实例说明:

代码:
#!/bin/bash
import os,sys
import time


def SetSession( ):
    os.setsid()
    time.sleep(100)

def CreateChild( ):
    if os.fork() == 0:
        SetSession( )
    else:
        # keep parent process alive!
        # because we will discover by "pstree -p"
        time.sleep(100)
if __name__ == "__main__":
    SetSession()


上面的代码直接在交互的bash下运行是为出现:

Traceback (most recent call last):
  File "test_session.py", line 19, in <module>
    SetSession()
  File "test_session.py", line 7, in SetSession
    os.setsid()
OSError: [Errno 1] Operation not permitted


因为test_session.py程序是交互的bash的第一代, 所以无法使用setsid系统调用.
如果将SetSession()换成调用CreateChild( ) 情况就不同了, 因为fork出的子进程是session leader的第二代!

        |-sshd(2051)---sshd(26494)---sshd(26502)---bash(26503)-+-less(26520)
        |                                                                                          |-less(27847)
        |                                                                                          |-pstree(27846)
        |                                                                                          |-python(27844)---python(27845)
        |                                                                                          `-vim(27694)---{vim}(27695)


上面的python(27844)---python(27845)就是我们要找的, 一个是父进程, 一个是子进程, 查一下子进程的session号:
jessinio@solution:~$ ps axo user,pid,rgid,session,command |grep 27845
jessinio 27845  1000 27845 python test_session.py

可以看出, 子进程的session ID被设置成与PID一样的数字

附: python cookbook上产生daemon进程的代码: http://www.ubookcase.com/book/Oreilly/Python.Cookbook.2nd.edition/0596007973/pythoncook2-chp-9-sect-13.html

其实, 现在版本的linux不会在用户logout后把特定的session进程都杀掉的. 下面还有一段话:


When the connection to a terminal is lost, the kernel sends a signal (SIGHUP; see Chapter 12 for more information on signals) to the leader of the session
containing the terminal's foreground process group, which is usually a
shell. This allows the shell to terminate the user's processes
unconditionally, notify the processes that the user has logged out
(usually, through a SIGHUP), or take some other action (or inaction). Although this setup may seem complicated, it lets the session
group leader decide how closed terminals should be handled rather than
putting that decision in the kernel. This allows system administrators
flexibile control over account policies.

* 这里只是指出foreground process ( group ), 没有提到background 的处理方法.
* 这种处理方法与shell有很大的相关性! 不过的shell可以有不同的处理方法

controlling terminal


Every session is tied to a terminal from which processes in the
session get their input and to which they send their output. That
terminal may be the machine's local console, a terminal connected over
a serial line, or a pseudo terminal that maps to an X window or across
a network (see Chapter 16 for information on pseudo terminal devices).
The terminal to which a session is related is called the controlling terminal (or controlling tty) of the session. A terminal can be the controlling terminal for only one session at a time.



Although the controlling terminal for a session can be changed, this
is usually done only by processes that manage a user's initial logging
in to a system.

* 来自Linux Application Development 一书

一个session, 是使用同一个terminal

process group

实际中, process group常常被用于job control. 本人需求不大

参考文档:
http://www.linuxforum.net/forum/gshowflat.php?Board=linuxK&Number=648409&page=3&o=
http://www.ibm.com/developerworks/cn/linux/l-cn-nohup/
http://www.informit.com/articles/article.aspx?p=397655&seqNum=6
http://en.wikipedia.org/wiki/Daemon_(computer_software)
http://www.win.tue.nl/~aeb/linux/lk/lk-10.html

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.