UNIX高级环境编程(12)进程关联(Process Relationships)- 终端登录过程 ,进程组,Session

在前面的章节我们了解到,进程之间是有关联的:

  • 每个进程都有一个父进程;
  • 子进程退出时,父进程可以感知并且获取子进程的退出状态。

本章我们将了解:

  • 进程组的更多细节;
  • sessions的内容;
  • login shell和我们从login shell启动的进程之间的关系。

?

一 终端登录(Terminal Logins)

BSD Terminal Logins

?BSD终端的登录程序在过去35年都没有改变。

  1. 系统管理员(the system adminstrator)创建一个文件 /etc/ttys,每一个登录终端都在该文件占一行,改行包含登录终端名,其他的参数则会传递给getty函数。
  2. 其中一个参数是终端的传输波特率(baud rate)。
  3. 当系统引导完成,内核创建init进程,进程ID为1。init进程负责引导系统启动。
  4. init进程读取文件/etc/ttys,并为每一个登录设备fork一个进程,然后执行exec运行getty程序。

?上面的流程如下图所示:

由init进程fork创建的进程的real user ID为0,effective user ID为0,并且他们都有超级用户权限。

程序getty的职责:为终端设备调用open函数,一旦设备被打开,文件描述符0,1,2被设置给该设备。然后getty输出一些提示符,等待我们输入用户名。当我们输入用户名后,getty的工作就完成了,然后通过调用exec函数执行登录函数,如下。

execle(“/bin/login”, “login”, “-p”, username, (char *)0, envp);

增加了login程序后,流程如下图所示:

上图中fork出来的进程都有超级用户权限,因为他们都是从init进程fork出来,而init进程有超级用户权限。

下面的进程的进程ID都是相同的,因为exec函数不改变进程的ID,并且他们的父进程的ID都是1。

现在登录程序转到login程序执行,login程序会做下面的事情:

  1. 根据我们输入的用户名,调用函数getpwnam获取用户名对应的密码;
  2. 调用函数getpass打印提示符 Password: ,等待读取我们输入的密码;
  3. 对我们输入的密码进行加密,将加密后的密码和从系统密码文件获取的密码进行对比,如果密码不同,则login程序调用exit函数退出,并返回退出状态1。init进程得到1的进程终止状态,则会再次执行fork进行登录重试。

如果我们正确登录,则login程序会继续做下面的事情:

  1. 当前工作目录切换到我们的主目录(chdir);
  2. 改变我们的终端设备的所有权为我们自己所有(chown);
  3. 改变我们的终端设备的权限,使得我们可以从该终端设备读取和输入;
  4. 设置我们的组ID(setgid和initgroups);
  5. 初始化我们的环境变量;
  6. 改变我们的用户ID(setuid),激活我们的登录shell ,如execl(“/bin/sh”, “-sh”, (char *)0);

?过程如下图所示:

我们的shell已经启动后,会去读取启动文件(.profile或.bash_profile或.bash_login或.profile,不同的系统启动文件的命名不同)。这些启动文件的作用是增加系统的环境变量,设置一些全局变量,链接等。

?

2 网络登录(Network Logins)

物理登录和网络登录的区别在于:登录终端到主机的连接是否是点对点的。

网络登录情况下,登录是一种可用服务,就像其他的服务,如FTP或SMTP。

网络登录服务特点是不知道会有多少登录请求会来。所以内核不是在等待每一个可能的登录,而是通过网络接口驱动(network interface drivers)在等待一个网络连接登录请求。

为了统一处理物理登录和网络登录,一个软件驱动,叫做虚拟终端(pseudo terminal)被用来用将网络登录后的行为请求映射为真实终端的行为。

BSD Network Logins

进程inetd等待处理大部分的网络连接。

下面我们将了解网络登录的过程。

  1. 系统启动时,init进程创建一个shell执行脚本/etc/rc,其中一个后台进程就是inetd。一旦该脚本终止,inetd进程的父进程就成为了init进程;
  2. inetd的职责是等待TCP/IP连接请求,一旦有新的连接请求到来,inetd会执行fork and exec执行相应的处理程序;
  3. telnetd程序会启动一个TELNET服务器,等待用户远程登录,用户通过TCP协议链接服务器,并通过合法的用户密码进行登录。

启动telnetd程序的过程如下图所示:

?

telnetd进程启动后的动作为:

  1. 打开一个虚拟终端(pseudo teminal),然后调用fork创建出两个进程;
  2. 父进程处理来自网络的连接请求;
  3. 子进程执行exec函数调用login程序;
  4. 父进程和子进程通过虚拟终端链接;
  5. 如果子进程正确登录,则后面的过程和物理登录相同。

过程如下图所示:

?

?3 进程组(Process Groups)

每一个进程都属于一个进程组。

进程组是一些进程的集合,这些进程常常关联于同一个job,并且从同一个终端接收信号。

每一个进程组都有一个唯一的进程组ID。

函数getpgrp返回调用进程的进程组ID。

函数声明:

?#include <unistd.h>

pid_t getpgrp(void);

? ? ? ? // Returns: process group ID of calling process

?

pid_t getpgid(pid_t pid);

? ? ? ? // Returns: process group ID if OK, -1 on error

函数调用getpgid(0); 和函数调用getpgrp(); 作用相同,都返回调用进程的进程组ID。

每个进程组都有个头进程,该进程的进程ID和进程组ID相同。

进程组的生命周期:从一个进程创建一个组开始,只到最有一个组内进程终止或者成为另外一个组的进程为止。

一个进程可以调用函数setpgid加入到另一个进程组或者创建一个进程组。

函数声明:

?#include <unistd.h>

int setpgid(pid_t pid, pid_t pgid);

函数设置进程ID为pid的进程的进程组ID为pgid。

如果pid和pgid相同,都为某个进程的进程ID,则进程pid成为一个进程组的头进程。

如果pid为0,则表示待设置的进程为当前进程。

?

4 Sessions

一个session是一个或几个进程组的集合。

例如下图所示:

一个进程通过调用函数setsid创建一个新的session。

函数声明:

?#include <unistd.h>

pid_t setsid(void);

? ? ? ? // Returns: process group ID if OK, -1 on error

如果调用进程不是组头进程,则会发生三件事:

  1. 该进程成为创建的新session的session leader;
  2. 该进程成为一个新进程组的头进程,新进程组ID为该调用进程的进程号;
  3. 该进程不关联终端。

函数getsid返回一个session leader进程的进程组ID。

函数声明:

#include <unistd.h>

pid_t getsid(pid_t pid);

? ? ? ? // Returns: session leader’s process group ID if OK, -1 on error

如果pid为0,函数getsid返回调用进程所在的session leader进程的进程组号。

?

?

参考资料:

《Advanced Programming in the UNIX Envinronment 3rd》

?

时间: 2024-08-09 10:44:49

UNIX高级环境编程(12)进程关联(Process Relationships)- 终端登录过程 ,进程组,Session的相关文章

《unix高级环境编程》终端 I/O——终端 IO 基本概述

终端基本概念 终端 IO 是一种字符型设备,终端特殊设备文件一般有以下几种: 串行端口终端:是使用计算机串行端口连接的设备,计算机把每个串行端口都看作是一个字符设备.串行端口所对应的设备名称 /dev/ttySn(n表示从0开始的整数): 伪终端:是成对的逻辑终端设备,例如 /dev/ptyp3 和/ dev/ttyp3(在设备文件系统中分别是 /dev/pty/m3 和/ dev/pty/s3 ),它们与实际物理设备并不直接相关: 控制终端:是当前进程的控制终端的设备特殊文件 /dev/tty

UNIX高级环境编程(9)进程控制(Process Control)- fork,vfork,僵尸进程,wait和waitpid

本章包含内容有: 创建新进程 程序执行(program execution) 进程终止(process termination) 进程的各种ID ? 1 进程标识符(Process Identifiers) 每个进程都有一个唯一的标识符,进程ID(process ID). 进程的ID是可重用的,如果一个进程被终止,那么它的进程ID会被系统回收,但是会延迟使用,防止该进程ID标识的新进程被误认为是以前的进程. 三个特殊ID的进程: Process ID 0:调度者进程,内核进程. Process

UNIX高级环境编程(11)进程控制(Process Control)- 进程快照,用户标识符,进程调度

1 进程快照(Process Accounting) 当一个进程终止时,内核会为该进程保存一些数据,包括命令的小部分二进制数据.CPU time.启动时间.用户Id和组Id.这样的过程称为process accounting,本篇译为进程快照. 函数acct可以打开或关闭进程快照功能. 负责记录快照的数据结构如下所示: 成员说明: ac_flag成员记录进程执行过程中的特定事件(稍后的表中会详细说明): 进程创建时,初始化进程快照的数据在进程表(process table)中,但是只有在进程终止

UNIX高级环境编程(8)进程环境(Process Environment)- 进程的启动和退出、内存布局、环境变量列表

在学习进程控制相关知识之前,我们需要了解一个单进程的运行环境. 本章我们将了解一下的内容: 程序运行时,main函数是如何被调用的: 命令行参数是如何被传入到程序中的: 一个典型的内存布局是怎样的: 如何分配内存: 程序如何使用环境变量: 程序终止的各种方式: 跳转(longjmp和setjmp)函数的工作方式,以及如何和栈交互: 进程的资源限制 ? 1 main函数 main函数声明: int main (int argc, char *argv[]); 参数说明: argc:命令行参数个数

UNIX高级环境编程(2)FIle I/O - 原子操作、共享文件描述符和I/O控制函数

引言: 本篇通过对open函数的讨论,引入原子操作,多进程通信(共享文件描述符)和内核相关的数据结构. 还会讨论集中常见的文件IO控制函数,包括: dup和dup2 sync,fsync和fdatasync fcntl ioctl /dev/fd ? 一.文件共享 这里所说的文件共享主要指的是进程间共享打开的文件. 这一节主要讨论文件在进程间共享的理论基础和数据结构,不涉及具体的技术实现,不同的系统可能会有不同的实现. 每一个打开的文件,涉及内核中的三种数据结构,这三种数据结构也是文件在进程间共

UNIX高级环境编程--1

前期准备: 下载apue3源文件(从apuebook.com上),然后编译(make)之后,得到libapue.a动态链接文件(.o 就相当于windows里的obj文件 .a 是好多个.o合在一起,用于静态连接 .so 是shared object,用于动态连接的,和dll差不多). 把apue.h放到 usr/include中,libapue.a放到usr/local/lib中. 如果想要在IDE中编译书中的source_code.c那么要记得设置项目或者文件的 "build option&

UNIX高级环境编程(13)信号 - 概念、signal函数、可重入函数

信号就是软中断. 信号提供了异步处理事件的一种方式.例如,用户在终端按下结束进程键,使一个进程提前终止. ? 1 信号的概念 每一个信号都有一个名字,它们的名字都以SIG打头.例如,每当进程调用了abort函数时,都会产生一个SIGABRT信号. 每一个信号对应一个正整数,定义在头文件<signal.h>中. 没有信号对应整数0,kill函数使用信号编号0表示一种特殊情况,所以信号编号0又叫做空信号(null signal). 下面的各种情况会产生一个信号: 当用户在终端按下特定的键时,会产生

UNIX高级环境编程(15)进程和内存分配 &lt; 故宫角楼 &gt;

故宫角楼是很多摄影爱好者常去的地方,夕阳余辉下的故宫角楼平静而安详. ? 首先,了解一下进程的基本概念,进程在内存中布局和内容. 此外,还需要知道运行时是如何为动态数据结构(如链表和二叉树)分配额外内存的. 一 进程 1 进程和程序 进程:是一个可执行程序的实例. 程序:包含一系列信息的文件,这些信息描述了如何在运行时创建一个进程.包含如下信息: 二进制格式标识:如最常见的ELF格式. 机器语言指令:对程序算法进行编码. 程序入口地址:标识程序开始执行时的起始指令位置. 数据:程序文件包含的变量

UNIX高级环境编程(3)Files And Directories - stat函数,文件类型,和各种ID

在前面的两篇,我们了解了IO操作的一些基本操作函数,包括open.read和write. 在本篇我们来学习一下文件系统的其他特性和一个文件的属性,涉及的函数功能包括: 查看文件的所有属性: 改变文件所有者: 改变文件权限: 操作文件夹. 我们还会了解一些文件系统相关的数据结构和符号链接(symbolic link). 1 函数stat.fstat.fstatat.lsat函数 #include <sys/stat.h> int stat(const char *restrict pathnam