`
shake863
  • 浏览: 637439 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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;
}
}

/*
* 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;

/* 第二前提: 先要检查做这个操作的权限:
当前进程只能将自身和其子进程设置为进程组id,并且
当前进程和其子进程必须属于同一次会话
(同组的进程一定属于同一次会话)
*/
if (p->p_pptr == current || p->p_opptr == current)
{
err = -EPERM;

/*如果不属于同一次会话(同一次控制台),不可以*/
if (p->session != current->session)
goto out;
err = -EACCES;

/*某个子进程调用 exec 函数之后, 就不能再将该子进程的 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)
{
/*能不能找到一个进程,组号正好是要设定的组号,
并且和要设定的进程属于同一个控制台(同一个会话)
找到才可以设定,其实这里就是要判定组号的合法性,
即必须是一个已经存在的组,而且和当前同一次会话才
可以操作,这个也不能忘记,其实就是说:同组的进程
一定属于同一次会话*/
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;
}

/*将新创建会话的leader设定为创建者就是当前进程*/
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;

}

分享到:
评论

相关推荐

    linux内核 0.11版本源码 带中文注释

    * 我们需要下面这些内嵌语句 - 从内核空间创建进程(forking)将导致没有写时复制(COPY ON WRITE)!!! * 直到一个执行execve 调用。这对堆栈可能带来问题。处理的方法是在fork()调用之后不让main()使用 * 任何堆栈...

    Linux内核源代码情景分析

    《LINUX内核源代码情景分析(上册)》采取类似于英语教学中行之有效的情景会话的教学方法,全面深入地剖析了Linux最新版本核心源代码,并对Linux核心的独特优点和需要进一步改进的问题作了精辟的评述。《LINUX内核源...

    Linux内核完全剖析

    本书采取类似于英语教学中行之有效的情景会话的教学方法,全面深入地剖析了Linux最新版本(2.4.0)核心源代码,并对Linux核心的独特优点和需要进一步改进的问题作了精辟的评述。 全书分上下两册。上册包括预备知识...

    the_colonel:带有键盘记录器和内置 IRC bot 的实验性 linux 内核模块 (rootkit)

    上校 | | | | Colonel 是一个实验性的 linux 内核模块 (rootkit) 和键盘记录器。 远程通信是通过包含的 IRC 机器人处理的。 上校能够: 记录键盘输入 授予root权限 ... 在私人消息或 DCC 会话中,命令应该

    Linux无盘工作站搭建

    内核文件的名称和位置在配置文件中给出,同样需要通过TFTP会话过程获取;内核文件获取成功后,系统开始进行本地启动,当启动过程进行到需要装载文件系统时,PXE会根据配置文件,向服务器请求连接根文件系统(该文件...

    《精通Linux 设备驱动程序开发》.(Sreekrishnan).pdf

     本书适合中高级linux开发人员阅读。 目录 第1章 引言1 1.1 演进1 1.2 gnu copyleft2 1.3 kernel.org2 1.4 邮件列表和论坛3 1.5 linux发行版3 1.6 查看源代码4 1.7 编译内核7 1.8 可加载的模块...

    嵌入式系统/ARM技术中的基于Linux内核模式的PPPoE优化与实现

    PPPOE(Point.to.Point Protoeol over Ethernet)是将PPP协议封装在以太网帧上进行传输,它的通信过程分为探测(Discovery)和PPP会话(Session)2个阶段。PPPoE Discovery阶段主要是客户机确定AC(Access Concentrator)...

    精通LINUX设备驱动程序开发

    引言 1 1.1 演进 1 1.2 gnu copyleft 2 1.3 kernel.org 2 1.4 邮件列表和论坛 3 1.5 linux发行版 3 1.6 查看源代码 4 1.7 编译内核 7 1.8 可加载的模块 8 1.9 整装待发 9 第2章 内核 11 2.1 启动过程 ...

    ARM_Linux启动分析.pdf

    这一部分的启动过程在2.4.x内核中简化了不少,缺省的独立初始化过程只剩下网络 (sock_init())和创建事件管理核心线程,而其他所需要的初始化都使用__initcall()宏 包含在do_initcalls()函数中启动执行。...

    firejail:Linux 命名空间沙箱程序-开源

    所有安全功能都直接在 Linux 内核中实现,并可在任何 Linux 计算机上使用。 Firejail 可以沙箱处理任何类型的进程:服务器、图形应用程序,甚至用户登录会话。 该软件包括大量 Linux 程序的安全配置文件:Mozilla ...

    Linux高性能服务器编程

    7.1.2 syslog函数 7.2 用户信息 7.2.1 UID、EUID、GID和EGID 7.2.2 切换用户 7.3 进程间关系 7.3.1 进程组 7.3.2 会话 7.3.3 用ps命令查看进程关系 7.4 系统资源限制 7.5 改变工作目录和根目录 7.6 ...

    操作系统安全:var log xferlog.docx

    Linux系统内核和许多程序会产生各种错误信息、警告信息和其他的提示信息,这些信息对管理员了解系统的运行状态是非常有用的,所以应该把它们写到日志文件中去。 完成这个过程的程序就是syslog。syslog可以根据日志的...

    MT7630E_3.16:3.16内核下原驱动的修改

    Mediatek MT7630E Combo Linux 驱动...要编译库并在 /lib/firmware 中复制固件,请运行(在 /lib/firmware 中的复制过程中会提示您输入 sudo 密码): make compile 要仅为当前会话加载和编译驱动程序(wifi 和蓝牙

    firejail:Linux名称空间和seccomp-bpf沙箱

    Firejail可以在SELinux或AppArmor环境中工作,并且与Linux控制组集成在一起。 该软件使用C语言编写,几乎没有任何依赖关系,可在任何3.x或更高版本内核Linux计算机上运行。 它可以对任何类型的进程进行沙箱处理:...

    dynbw:适用于Android的内核源代码的Dynamic Build Wrapper

    它的目标是简化和自动化构建内核的过程,以适应内核构建方案的新手。 几乎与所有使用POSIX SH的设备兼容。 这保证了与大多数Linux发行版之间的广泛和广泛的兼容性,甚至与那些非Linux发行版但可以使用POSIX SH的...

Global site tag (gtag.js) - Google Analytics