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

Linux内核中的进程组及会话

将阐述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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值