Linux中的进程组及会话
將闡述Linux內(nèi)核中的如下幾個概念?
1) 進(jìn)程組?
2) 會話?
3) 控制終端?
前面的概念來源于前人,我只是站在前人的肩膀上結(jié)合內(nèi)核中的實(shí)現(xiàn)加深概念理解。?
1.概念:?
a)進(jìn)程組?
Shell 上的一條命令行形成一個進(jìn)程組?
每個進(jìn)程屬于一個進(jìn)程組?
每個進(jìn)程組有一個領(lǐng)頭進(jìn)程?
進(jìn)程組的生命周期到組中最后一個進(jìn)程終止, 或加入其他進(jìn)程組為止?
getpgrp: 獲得進(jìn)程組 id, 即領(lǐng)頭進(jìn)程的 pid?
setpgid: 加入進(jìn)程組和建立新的進(jìn)程組?
前臺進(jìn)程組和后臺進(jìn)程組?
===============================================================================?
#include <unistd.h>?
int setpgid (pid_t pid, pid_t pgid);?
pid_t getpgid (pid_t pid);?
int setpgrp (void);?
pid_t getpgrp (void);?
-------------------------------------------------------------------------------?
進(jìn)程只能將自身和其子進(jìn)程設(shè)置為進(jìn)程組 id.?
某個子進(jìn)程調(diào)用 exec 函數(shù)之后, 就不能再將該子進(jìn)程的 id 作為進(jìn)程組 id.?
===============================================================================?
b)會話?
一次登錄形成一個會話?
一個會話可包含多個進(jìn)程組, 但只能有一個前臺進(jìn)程組.?
setsid 可建立一個新的會話?
===============================================================================?
#include <unistd.h>?
pid_t setsid(void);?
-------------------------------------------------------------------------------?
如果調(diào)用進(jìn)程不是進(jìn)程組的領(lǐng)頭進(jìn)程, 該函數(shù)才能建立新的會話.?
調(diào)用 setsid 之后, 進(jìn)程成為新會話的領(lǐng)頭進(jìn)程.?
進(jìn)程成為新進(jìn)程組的領(lǐng)頭進(jìn)程.?
進(jìn)程失去控制終端?
===============================================================================?
c)控制終端?
會話的領(lǐng)頭進(jìn)程打開一個終端之后, 該終端就成為該會話的控制終端 (SVR4/Linux)?
與控制終端建立連接的會話領(lǐng)頭進(jìn)程稱為控制進(jìn)程 (session leader)?
一個會話只能有一個控制終端?
產(chǎn)生在控制終端上的輸入和信號將發(fā)送給會話的前臺進(jìn)程組中的所有進(jìn)程?
終端上的連接斷開時 (比如網(wǎng)絡(luò)斷開或 Modem 斷開), 掛起信號將發(fā)送到控制進(jìn)程(session leader)?
2. Linux中的實(shí)現(xiàn)舉例,用以驗(yà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);?
/*第一前提: 先要驗(yàn)證要設(shè)定的進(jìn)程是否存在,不存在的話不能做事*/?
err = -ESRCH;?
p = find_task_by_pid(pid);?
if (!p)?
goto out;?
/* 第二前提: 先要檢查做這個操作的權(quán)限:?
當(dāng)前進(jìn)程只能將自身和其子進(jìn)程設(shè)置為進(jìn)程組id,并且?
當(dāng)前進(jìn)程和其子進(jìn)程必須屬于同一次會話?
(同組的進(jìn)程一定屬于同一次會話)?
*/?
if (p->p_pptr == current || p->p_opptr == current)?
{?
err = -EPERM;?
/*如果不屬于同一次會話(同一次控制臺),不可以*/?
if (p->session != current->session)?
goto out;?
err = -EACCES;?
/*某個子進(jìn)程調(diào)用 exec 函數(shù)之后, 就不能再將該子進(jìn)程的 id 作為進(jìn)程組 id*/?
if (p->did_exec)?
goto out;?
}?
else if (p != current)?
goto out;?
err = -EPERM;?
/*boolean value for session group leader */?
/*如果是一次會話的leader,也不可以?
注意進(jìn)程組的首領(lǐng)進(jìn)程也是可以改變組id的*/?
if (p->leader)?
goto out;?
/*好!幾個前提條件全滿足了,要做正事了:?
但是是不是組號的合法性還沒有驗(yàn)證?見后話!*/?
/*要設(shè)進(jìn)程號不是要設(shè)定的組號,如果是,直接設(shè),因?yàn)檫@?
意味著是增加了以自己的pid作為新的組號的進(jìn)程組,這個?
進(jìn)程也將成為新進(jìn)程組的首領(lǐng)進(jìn)程,所以在此根本不用比較?
會話號,自己對自己肯定是同一次會話.如果條件不滿足,則?
要做這些判斷*/?
if (pgid != pid)?
{?
struct task_struct * tmp;?
for_each_task (tmp)?
{?
/*能不能找到一個進(jìn)程,組號正好是要設(shè)定的組號,?
并且和要設(shè)定的進(jìn)程屬于同一個控制臺(同一個會話)?
找到才可以設(shè)定,其實(shí)這里就是要判定組號的合法性,?
即必須是一個已經(jīng)存在的組,而且和當(dāng)前同一次會話才?
可以操作,這個也不能忘記,其實(shí)就是說:同組的進(jìn)程?
一定屬于同一次會話*/?
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)?
{?
/*如果當(dāng)前進(jìn)程是一個進(jìn)程組的首領(lǐng)進(jìn)程,?
則不能建立一個新的會話*/?
if (p->pgrp == current->pid)?
goto out;?
}?
/*將新創(chuàng)建會話的leader設(shè)定為創(chuàng)建者就是當(dāng)前進(jìn)程*/?
current->leader = 1;?
/*清楚看見一個新的進(jìn)程組誕生了?
當(dāng)前進(jìn)程成為新進(jìn)程組的首領(lǐng)進(jìn)程?
新會話的id 是當(dāng)前進(jìn)程號,也是新會話的leader?
*/?
current->session = current->pgrp = current->pid;?
/*當(dāng)前進(jìn)程失去控制終端*/?
current->tty = NULL;?
current->tty_old_pgrp = 0;?
err = current->pgrp;?
out:?
read_unlock(&tasklist_lock);?
return err;?
}
總結(jié)
以上是生活随笔為你收集整理的Linux中的进程组及会话的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何安装 Linux 下的 Adobe
- 下一篇: linux中fork和exec