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