您的位置:首页 > 运维架构 > Linux

【转】Linux内核中的进程组…

2013-11-28 12:47 288 查看
原文地址:【转】Linux内核中的进程组及会话作者:lihongliang070Linux内核中的进程组及会话

将阐述Linux内核中的如下几个概念

1) 进程组

2) 会话

3) 控制终端

前面的概念来源于前人,我只是站在前人的肩膀上结合内核中的实现加深概念理解。

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.

    某个子进程调用 exec
函数之后, 就不能再将该子进程的 id 作为进程组 id.

===============================================================================

b)会话

一次登录形成一个会话

一个会话可包含多个进程组, 但只能有一个前台进程组.

setsid 可建立一个新的会话

===============================================================================

      
#include <unistd.h>

      
pid_t setsid(void);

-------------------------------------------------------------------------------

   
如果调用进程不是进程组的领头进程, 该函数才能建立新的会话.

    调用 setsid
之后, 进程成为新会话的领头进程.

   
进程成为新进程组的领头进程.

   
进程失去控制终端

===============================================================================

c)控制终端

会话的领头进程打开一个终端之后, 该终端就成为该会话的控制终端 (SVR4/Linux)

与控制终端建立连接的会话领头进程称为控制进程 (session leader)

一个会话只能有一个控制终端

产生在控制终端上的输入和信号将发送给会话的前台进程组中的所有进程

终端上的连接断开时 (比如网络断开或 Modem 断开), 挂起信号将发送到控制进程(session leader)

2. Linux中的实现举例,用以验证上述规则:

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;

}

}

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;

read_lock(&tasklist_lock);

err = -ESRCH;

p = find_task_by_pid(pid);

if (!p)

goto out;

if (p->p_pptr == current ||
p->p_opptr == current)

{

err = -EPERM;

if (p->session !=
current->session)

goto out;

err = -EACCES;

if (p->did_exec)

goto out;

}

else if (p != current)

goto out;

err = -EPERM;

if (p->leader)

goto out;

if (pgid != pid)

{

struct task_struct * tmp;

for_each_task (tmp)

{

if (tmp->pgrp == pgid
&&

tmp->session ==
current->session)

goto ok_pgid;

}

goto out;

}

ok_pgid:

p->pgrp = pgid;

err = 0;

out:

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;

}

current->leader = 1;

current->session = current->pgrp =
current->pid;

current->tty = NULL;

current->tty_old_pgrp = 0;

err = current->pgrp;

out:

read_unlock(&tasklist_lock);

return err;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: