Linux内核中的进程组及会话
Linux內(nèi)核中的進程組及會話
將闡述Linux內(nèi)核中的如下幾個概念
1) 進程組
2) 會話
3) 控制終端
前面的概念來源于前人,我只是站在前人的肩膀上結(jié)合內(nèi)核中的實現(xiàn)加深概念理解。
1.概念:
a)進程組
Shell 上的一條命令行形成一個進程組
每個進程屬于一個進程組
每個進程組有一個領頭進程
進程組的生命周期到組中最后一個進程終止, 或加入其他進程組為止
getpgrp: 獲得進程組 id, 即領頭進程的 pid
setpgid: 加入進程組和建立新的進程組
前臺進程組和后臺進程組
===============================================================================
?????? #include <unistd.h>
??????? int setpgid (pid_t pid, pid_t pgid);
??????? pid_t getpgid (pid_t pid);
??????? int setpgrp (void);
??????? pid_t getpgrp (void);
-------------------------------------------------------------------------------
??? 進程只能將自身和其子進程設置為進程組 id.
??? 某個子進程調(diào)用 exec 函數(shù)之后, 就不能再將該子進程的 id 作為進程組 id.
===============================================================================
b)會話
一次登錄形成一個會話
一個會話可包含多個進程組, 但只能有一個前臺進程組.
setsid 可建立一個新的會話
===============================================================================
?????? #include <unistd.h>
?????? pid_t setsid(void);
-------------------------------------------------------------------------------
??? 如果調(diào)用進程不是進程組的領頭進程, 該函數(shù)才能建立新的會話.
??? 調(diào)用 setsid 之后, 進程成為新會話的領頭進程.
??? 進程成為新進程組的領頭進程.
??? 進程失去控制終端
===============================================================================
c)控制終端
會話的領頭進程打開一個終端之后, 該終端就成為該會話的控制終端 (SVR4/Linux)
與控制終端建立連接的會話領頭進程稱為控制進程 (session leader)
一個會話只能有一個控制終端
產(chǎn)生在控制終端上的輸入和信號將發(fā)送給會話的前臺進程組中的所有進程
終端上的連接斷開時 (比如網(wǎng)絡斷開或 Modem 斷開), 掛起信號將發(fā)送到控制進程(session leader)
2. Linux中的實現(xiàn)舉例,用以驗證上述規(guī)則:
asmlinkage long sys_getpgid(pid_t pid)
{
?if (!pid) {
??return current->pgrp;
?} else {
??int retval;
??struct task_struct *p;
??read_lock(&tasklist_lock);
??p = find_task_by_pid(pid);
??retval = -ESRCH;
??if (p)
???retval = p->pgrp;
??read_unlock(&tasklist_lock);
??return retval;
?}
}
/*
?* This needs some heavy checking ...
?* I just haven't the stomach for it. I also don't fully
?* understand sessions/pgrp etc. Let somebody who does explain it.
?*
?* OK, I think I have the protection semantics right.... this is really
?* only important on a multi-user system anyway, to make sure one user
?* can't send a signal to a process owned by another.? -TYT, 12/12/91
?*
?* Auch. Had to add the 'did_exec' flag to conform completely to POSIX.
?* LBT 04.03.94
?*/
asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
{
?struct task_struct * p;
?int err = -EINVAL;
?if (!pid)
??pid = current->pid;
?if (!pgid)
??pgid = pid;
?if (pgid < 0)
??return -EINVAL;
?/* From this point forward we keep holding onto the tasklist lock
? * so that our parent does not change from under us. -DaveM
? */
?read_lock(&tasklist_lock);
????? /*第一前提: 先要驗證要設定的進程是否存在,不存在的話不能做事*/
?err = -ESRCH;
?p = find_task_by_pid(pid);
?if (!p)
??goto out;
???
????? /* 第二前提:? 先要檢查做這個操作的權(quán)限:
????? 當前進程只能將自身和其子進程設置為進程組id,并且
????? 當前進程和其子進程必須屬于同一次會話
????? (同組的進程一定屬于同一次會話)
????? */
?if (p->p_pptr == current || p->p_opptr == current)
????? {
??err = -EPERM;
???????????? /*如果不屬于同一次會話(同一次控制臺),不可以*/
??if (p->session != current->session)
???goto out;
??err = -EACCES;
???????????? /*某個子進程調(diào)用 exec 函數(shù)之后, 就不能再將該子進程的 id 作為進程組 id*/
??if (p->did_exec)
???goto out;
?}
????? else if (p != current)
??goto out;
???
?err = -EPERM;
????? /*boolean value for session group leader */
????? /*如果是一次會話的leader,也不可以
????? 注意進程組的首領進程也是可以改變組id的*/
?if (p->leader)
??goto out;
??? /*好!幾個前提條件全滿足了,要做正事了:
??? 但是是不是組號的合法性還沒有驗證?見后話!*/
???
??? /*要設進程號不是要設定的組號,如果是,直接設,因為這
????? 意味著是增加了以自己的pid作為新的組號的進程組,這個
????? 進程也將成為新進程組的首領進程,所以在此根本不用比較
????? 會話號,自己對自己肯定是同一次會話.如果條件不滿足,則
????? 要做這些判斷*/
?if (pgid != pid)
????? {
??struct task_struct * tmp;
??for_each_task (tmp)
??????????? {
?????????????????? /*能不能找到一個進程,組號正好是要設定的組號,
?????????????????? 并且和要設定的進程屬于同一個控制臺(同一個會話)
?????????????????? 找到才可以設定,其實這里就是要判定組號的合法性,
?????????????????? 即必須是一個已經(jīng)存在的組,而且和當前同一次會話才
?????????????????? 可以操作,這個也不能忘記,其實就是說:同組的進程
?????????????????? 一定屬于同一次會話*/
???if (tmp->pgrp == pgid &&???????????????
?????? tmp->session == current->session)
????goto ok_pgid;
??}
??goto out;
?}
ok_pgid:
?p->pgrp = pgid;
?err = 0;
out:
?/* All paths lead to here, thus we are safe. -DaveM */
?read_unlock(&tasklist_lock);
?return err;
}
asmlinkage long sys_getsid(pid_t pid)
{
?if (!pid) {
??return current->session;
?} else {
??int retval;
??struct task_struct *p;
??read_lock(&tasklist_lock);
??p = find_task_by_pid(pid);
??retval = -ESRCH;
??if(p)
???retval = p->session;
??read_unlock(&tasklist_lock);
??return retval;
?}
}
asmlinkage long sys_setsid(void)
{
?struct task_struct * p;
?int err = -EPERM;
?read_lock(&tasklist_lock);
?for_each_task(p)
????? {
???????????? /*如果當前進程是一個進程組的首領進程,
???????????? 則不能建立一個新的會話*/
??if (p->pgrp == current->pid)
???goto out;
?}
????? /*將新創(chuàng)建會話的leader設定為創(chuàng)建者就是當前進程*/
?current->leader = 1;
????? /*清楚看見一個新的進程組誕生了
????? 當前進程成為新進程組的首領進程
????? 新會話的id 是當前進程號,也是新會話的leader
????? */
?current->session = current->pgrp = current->pid;
??/*當前進程失去控制終端*/
?current->tty = NULL;
?current->tty_old_pgrp = 0;
?err = current->pgrp;
out:
?read_unlock(&tasklist_lock);
?return err;
}
?
?
轉(zhuǎn)自:http://chongsoft.blogchina.com/chongsoft/6275856.html
總結(jié)
以上是生活随笔為你收集整理的Linux内核中的进程组及会话的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQLite VC环境搭建
- 下一篇: Linux进程状态解析