《UNUX环境高级编程》(9)进程关系

news2024/11/24 4:27:06

1、前言

2、终端登录

  • 在早期的UNIX系统,用户用哑终端(用硬连接到主机)进行登录,因为连接到主机上的终端设备数是固定的,所以同时登录数也就有了已知的上限。

  • 随着位映射图像终端的出现,开发出了窗口系统,它向用户提供了与主机系统进行交互的新方式。创建终端窗口的应用也被开发出来,它仿真了基于字符的终端,使得用户可用用熟悉的方式(即shell命令)与主机进行交互。

  • 我们现在描述的过程用于经由终端登录至UNIX系统。该过程几乎与所使用的终端类型无关,所使用的终端可以是基于字符的终端、仿真基于字符的终端,或者运行窗口系统的图形终端

  • 这里说明两种平台的终端登录:

    • BSD终端登录
      BSD的终端登录过程比较经典,linux也是其后继者。

      • 系统管理者创建通常名为/etc/ttys的文件,其中每个终端设备都有一行,每行说明设备名和传到getty程序的参数。例如其中一个参数说明了波特率等等。

      • 当系统自举时,内核创建进程ID为1的进程,也就是init进程。

      • init进程使系统进入多用户模式。

      • init读取/etc/ttys,对每一个允许登录的终端设备,init调用一次fork,它所生成的子进程则exec getty(get teletypewriter) 程序。init以空环境exec getty程序。

      • getty对终端设备调用open函数,以读、写方式打开终端,此时会得到该终端的文件描述符。一旦该设备被打开,文件描述符012就被通过dup2函数关联到一起,从而共享终端设备的文件表项。然后getty输出“login :”之类的信息,并等待用户键入用户名。

      • 当用户键入了用户名后,getty的工作就完成了。然后它以类似于以下方式调用login程序:

        execle("/bin/login","login","-p",username,(char *)0,envp);
        
      • 其中envp环境变量是根据gettytab文件中的环境字符串生成的,“-p”参数通知login保留传递给它的环境,也可以将其它环境字符串添加到该环境中,但是不要替换它。

      在这里插入图片描述

      • login能处理多项工作。因为它得到了用户名,所以能调用getpwnam取得相应用户的口令文件登陆项。然后login调用getpass以显示“Password:”,接着读入用户键入的口令,它调用crypt将口令加密,并与该用户在阴影口令文件中登录项的pw_passwd字段相比较。

      • 如果用户几次键入的口令都无效,则login以参数1调用exit表示登陆失败。父进程(init)了解到子进程的终止情况后,将再次调用fork,然后又执行了getty,对此终端执行上述过程。
        在这里插入图片描述

      • 如果用户正确登录,login就将完成如下工作:

        • 将当前工作目录更改为该用户的起始目录(chdir)。
        • 调用chown更改该终端的所有权,使登录用户成为它的所有者。
        • 将对该终端设备的访问权限改变成“用户读和写”。
        • 调用setgidinitgroups设置进程的组ID。
        • login得到的所有信息初始化环境:起始目录、shell、用户名、以及一个系统默认路径(PATH).
        • login进程更改为登录用户的ID(setuid)并调用登录用户的shell,类似于:execl("/bin/sh","-sh",(char *)0);
      • 至此,用户登录的登录shell得以开始运行。其父进程是init进程,所以此shell终止时,init会得到通知(接收到SIGCHLD信号),它会对该终端重复全部上述过程。登录shell的文件描述符012设置为终端设备。

      • 现在,登录shell读取其启动文件(.profile),这些启动文件通常更改某些环节变量设置他们自己的PATH,当执行完启动文件后,用户最后得到shell提示符,并能键入命令

    • Linux终端登录

      • linux的终端登录过程非常类似于BSD,它们的主要区别在于说明终端配置的方式。
      • Ubuntu使用的init程序叫作“Upstart”,并使用存放在/etc/init目录的*.conf命名的配置文件。例如:运行/dev/tty1上的getty需要的说明可能放在/etc/init/tty1.conf文件中。

3、网络登录

  • 通过串行终端登录至系统和经由网络登录至系统两者之间的主要区别是:网络登录时,在终端和计算机之间的连接不再是点到点的。在网络登录情况下,login仅仅是一种可用的服务,这与其他网络服务(如FTPSMTP)性质相同。

  • 在上述的终端登录中,init知道哪些终端设备可用用来登录,并为每个设备生成一个getty进程。但是,对网络登录情况有所不同,因为事先并不知道有多少个这样的登录。因此必须等待一个网络连接请求的到达,而不是使一个进程等待每一个可能的登录。

  • 为使同一个软件既能处理终端登录,又能处理网络登录,系统使用了一种称为伪终端的软件驱动程序,它仿真串行终端的运行行为,并将终端操作映射为网络操作,反之亦然。

  • BSD网络登录

    • 在BSD中,有一个inetd进程(有时称为英特网超级服务器),它等待大多数网络连接。

    • 作为系统启动的一部分,init调用一个shell,使其执行shell脚本/etc/rc。由此shell脚本启动一个守护进程inetd。一旦此shell脚本终止,inetd的父进程就变成init

    • inetd等待TCP/IP连接请求到达主机,而当一个连接请求到达时,它执行一次fork,然后子进程exec适当的程序。
      在这里插入图片描述

    • telnet为例:

      • 主机A启动telnet客户端进程,通过 telnet hostname登录远端名为hostname的主机B。
      • 主机B的inetd进程收到来自主机A的请求。
      • 主机B的inetd进程fork一个子进程并exec主机B上的TELNET进程(被称为talnetd)。
      • 然后talnetd进程打开一个伪终端,并用fork分成两个进程。父进程通过网络连接的通行,子进程执行login程序。
    • 需要理解的是:当通过终端或网络登录时,我们得到一个登录shell,其标准输入、标准输出、标准错误连接到一个终端设备或一个伪终端上。后面将会了解到这一登录shell是一个会话的开始,而此终端或伪终端则是会话的控制终端。

      在这里插入图片描述

  • linux网络登录

    • 除了有些版本使用扩展的因特网服务进程xinetd代替inetd进程外,Linux网络登录的其他方面与BSD网络登录相同。xinetd进程对它所启动的各种服务的控制比inetd提供的控制更加精细。

4、进程组

  • 每个进程除了有一个进程ID外,还属于一个进程组。

  • 进程组是一个或多个进程的集合。通常,他们是在同一作业中结合起来的,同一进程组中的各进程接收来自同一终端的各种信号。每一个进程组有一个唯一的进程组ID。

  • 进程组ID类似于进程ID,它是一个正整数,并可存放在pid_t数据类型中。

    #include <unistd.h>
    pid_t getpgrp(void);       //返回调用进程的进程组ID.
    
    pid_t getpgid(pid_t pid);  //返回进程号为pid的进程组ID,若pid=0,则等价于getpgrp
    
  • 每个进程组有一个组长进程。组长进程的进程ID等于该进程组的进程组ID。

  • 只要在某个进程组中有一个进程存在,则该进程组就存在,这与其组长进程是否终止无关。从进程组创建开始到最后一个进程离开为止的时间区间称为进程组的生命周期。某个进程组中的最后一个进程可以终止,也可以转移到另一个新的进程组。

  • 进程调用setpgid可以创建一个进程组也可以键入到一个现有的进程组。

    #include <unistd.h>
    int setpgid(pid_t pid,pid_t pgid);  
    
    • setpgid函数将pid进程的进程组ID设置为pgid,如果这两个参数相等,则由pid 指定的进程变成进程组组长;
    • 如果pid=0,则使用调用者的进程ID;
    • 如果pgid=0,则由pid指定的进程ID用作进程组ID;
    • 一个进程只能为自己或它的子进程设置进程组ID。在它的子进程调用了exec后,他就不能更改该子进程的ID了。
  • 在大多数作业控制shell中,在fork之后调用此函数,使父进程设置其子进程进程组ID,并且也使子进程设置其自己的进程组ID,这两个调用中有一个是冗余的,但让父子进程都这样做可以保证,在父进程和子进程认为子进程已经进入了该进程组之前,这确实已经发生了。如果不这样做,在fork之后,由于父进程和子进程运行的先后顺序不确定,会因为子进程的组员身份取决于哪个进程首先执行而产生竞争条件。

5、 会话

  • 会话(session)是一个或多个进程组的集合。其结构可以如下,在一个会话中有3个进程组:
    这里写图片描述

  • 通常是由shell的管道将几个进程编成一组的。上面的安排可能由下列形式的shell命令形成:

    proc1 | proc2 & # 这是后台进程组
    proc3 | proc4 | proc5 # 这是前台进程组
    
  • 进程调用setsid函数建立一个新会话。

    #include <unistd.h>
    pid_t setsid(void);  
    
  • 如果调用此函数的进程不是一个进程组组长,则此函数创建一个新会话。具体会发生以下3件事:

    • 该进程会变成新会话的首进程session leader,会话首进程是创建该会话的进程)。此时,该进程是新会话中的唯一进程。
    • 该进程成为一个新进程组的组长进程。新进程组ID是该调用进程的进程ID。
    • 该进程没有控制终端,如果之前有一个控制终端,那么这种联系也被切断
  • 如果该调用进程已经是一个进程组的组长,则此函数返回出错。 为了保证不处于这种情况,通常先调用fork,然后使其父进程终止,而子进程则继续。因为子进程继承了父进程的进程组ID,而其进程ID则是新分配的,两者不可能相等,这就保证了子进程不是一个进程组的组长。

  • getsid函数返回会话首进程的进程组ID:

    #include <unistd.h>
    pid_t getsid(pid_t pid);  
    
    • 如果pid0getsid返回调用进程的会话首进程的进程组ID

6、控制终端

  • 控制终端对应的文件是/dev/tty

  • 这是一个逻辑概念,即用户正在控制的终端,可以为串行终端虚拟终端伪终端

    • 一个会话可以有一个控制终端(controlling terminal)。这通常是终端设备(在终端登录情况下)或伪终端设备(在网络登录情况下)。
    • 建立与控制终端连接的会话首进程被称为控制进程(controlling process) 。
      一个会话中的几个进程组可以被分成一个前台进程组(foreground process group)以及一个或多个后台进程组(background process group)。
    • 如果一个会话有一个控制终端,则它有一个前台进程组,其他进程组为后台进程组。
    • 无论何时键入终端的退出键(常常是ctrl+\),都会将退出信号发送至前台进程组的所以进程。
    • 如果终端接口检测到调制解调器或网络已经断开,则将挂断信号发送至控制进程(会话首进程)。
  • 以用户登录系统为例,可能存在如下图所示的情况:
    在这里插入图片描述

  • 通常我们不必担心控制终端,登录时,将自动建立控制终端(如通过终端登录Unix时,getty通过open函数以读写方式打开该终端设备,把文件描述符0、1、2都指向该控制终端)。

  • 如何为会话分配一个控制终端:

    • 当会话首进程打开第一个尚未与一个会话相关联的终端设备时,只要在调用open时没有O_NOCTTY,将会将此终端作为控制终端分配给该会话
    • 会话首进程以TIOCSCTTY作为request参数调用ioctl时,会为该会话分配控制终端。为了使此函数成功执行,此会话不能已经有一个控制终端(因此此操作通常跟在setsid调用之后,setsid保证此进程是一个没有控制终端的会话首进程)
  • 程序能与控制终端对话的方法是open文件/dev/tty,如果程序没有控制终端,则打开此设备将失败。

7、 函数tcgetpgrp、tcsetpgrp和tcgetsid

  • 需要一种方法来通知内核哪一个进程组是前台进程组,这样,终端设备驱动程序就能知道将终端输入和终端产生的信号发送到何处

    #include <unistd.h>
    pid_t tcgetpgrp(int fd);    //返回终端为fd的前台进程组ID
    int tcsetpgrp(int fd ,pid_t pgrpid);   //将前台进程组ID设置为pgrpid,终端为fd。
    
    • tcgetpgrp函数返回前台进程组ID,fd引用该会话的控制终端
    • tcsetpgrp函数将前台进程组ID设为pgrppgrp应为同一会话中的一个进程组ID,fd引用该会话的控制终端
  • 大多数应用程序不直接调用这两个函数,它们通常由作业控制shell调用

  • 通过tcgetsid函数获取控制终端的会话首进程的进程组ID

    #include <termios.h>
    pid_t tcgetsid(int fd);
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/761120.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数学分析:对偶映射

这个其实就是我们一致讨论的对偶映射&#xff0c;换了个马甲&#xff0c;差点认不出来了。本来是V->R 要变成U->R&#xff0c;就需要一个反向的V*->U*的映射。 注意这个式子&#xff0c;t属于U&#xff0c;phit转到了V&#xff0c;但是坐标也发生了变化&#xff0c;这…

2023西南赛区ciscn -- do you like read

Attack 打开后一个商城页面 在login as admin那里有个登录页面&#xff0c;账号admin&#xff0c;密码爆破即可得到admin123 也可以在book.php?bookisbn1进行sql注入得到密码&#xff0c;这里发现是没有注入waf的 登录进来是一个Book List的管理页面&#xff0c;同时在审计源…

【C语言】初阶指针(详细版)

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在回炉重造C语言&#xff08;2023暑假&#xff09; ✈️专栏&#xff1a;【C语言航路】 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你…

RSA原理

RSA的历史 RSA加密算法是一种非对称加密算法&#xff0c;在公开密钥加密和电子商业中被广泛使用。RSA是由罗纳德李维斯特&#xff08;Ron Rivest&#xff09;、阿迪萨莫尔&#xff08;Adi Shamir&#xff09;和伦纳德阿德曼&#xff08;Leonard Adleman&#xff09;在1977年一…

本地推理,单机运行,MacM1芯片系统基于大语言模型C++版本LLaMA部署“本地版”的ChatGPT

OpenAI公司基于GPT模型的ChatGPT风光无两&#xff0c;眼看它起朱楼&#xff0c;眼看它宴宾客&#xff0c;FaceBook终于坐不住了&#xff0c;发布了同样基于LLM的人工智能大语言模型LLaMA&#xff0c;号称包含70亿、130亿、330亿和650亿这4种参数规模的模型&#xff0c;参数是指…

Lightening Network for Low-Light Image Enhancement 论文阅读笔记

这是2022年TIP期刊的一篇有监督暗图增强的文章 网络结构如图所示&#xff1a; LBP的网络结构如下&#xff1a; 有点绕&#xff0c;其基于的理论如下。就是说&#xff0c;普通的暗图增强就只是走下图的L1红箭头&#xff0c;从暗图估计一个亮图。但是其实这个亮图和真实的亮图…

54 # 可写流基本用法

内部也是基于 events 模块&#xff0c;fs.open、fs.write&#xff0c;如果文件不存在就会创建文件&#xff0c;默认会清空文件并写入 注意点&#xff1a;可写流的 highWaterMark 表示预期占用的内存&#xff08;达到或者超过预期后返回的值就是false&#xff09;&#xff0c;默…

确认应答机制与超时重发机制【TCP原理(笔记一)】

文章目录 通过序列号与确认应答提高可靠性正常的数据传输数据包丢失的情况确认应答丢失的情况发送的数据 重发超时如何确定 通过序列号与确认应答提高可靠性 在TCP中&#xff0c;当发送端的数据到达接收主机时&#xff0c;接收端主机会返回一个已收到消息的通知。这个消息叫做…

TCP的三次握手以及以段为单位发送数据【TCP原理(笔记二)】

文章目录 连接管理TCP以段为单位发送数据 连接管理 TCP提供面向有连接的通信传输。面向有连接是指在数据通信开始之前先做好通信两端之间的准备工作。 UDP是一种面向无连接的通信协议&#xff0c;因此不检查对端是否可以通信&#xff0c;直接将UDP包发送出去。TCP与此相反&am…

2023-07-16:讲一讲Kafka与RocketMQ中零拷贝技术的运用?

2023-07-16&#xff1a;讲一讲Kafka与RocketMQ中零拷贝技术的运用&#xff1f; 答案2023-07-16&#xff1a; 什么是零拷贝? 零拷贝(英语: Zero-copy) 技术是指计算机执行操作时&#xff0c;CPU不需要先将数据从某处内存复制到另一个特定区域。这种技术通常用于通过网络传输…

layui的基本使用-Helloworld 三把斧的一把斧头的熟练起来

该笔记记录如何使用layui的模块化方法。 访问layui官网 Layui - 极简模块化前端 UI 组件库下载官网的layui压缩包文件&#xff0c;解压到本地文件夹&#xff0c;文件结构如下&#xff1a; vscode创建项目&#xff1b; 位置 测试写了三个文件夹&#xff0c;才测试出来bug 坑所在…

【深度学习笔记】偏差与方差

本专栏是网易云课堂人工智能课程《神经网络与深度学习》的学习笔记&#xff0c;视频由网易云课堂与 deeplearning.ai 联合出品&#xff0c;主讲人是吴恩达 Andrew Ng 教授。感兴趣的网友可以观看网易云课堂的视频进行深入学习&#xff0c;视频的链接如下&#xff1a; 神经网络和…

JAVASE-Java概述与环境搭建(一)

文章目录 一.内容摘要二.引言2.1.何为编程&#xff1f;2.2.什么是计算机编程语言&#xff1f;2.3.编程语言发展史2.3.1.打孔机2.3.2.汇编语言2.3.3.高级语言2.3.3.1.C语言2.3.3.2.C语言2.3.3.3.PHP语言2.3.3.4. .NET语言2.3.3.5. Ruby2.3.3.6. python2.3.3.7. Java 2.3.4.编程语…

代码随想录算法训练营之JAVA|第四天| 24. 两两交换链表中的节点

今天是第 天刷leetcode&#xff0c;立个flag&#xff0c;打卡60天。 算法挑战链接 力扣http://24. 两两交换链表中的节点 第一想法 看到题目的第一想法是交换节点&#xff0c;于是赶紧拿出草稿本画了出来。这不简简单单。 1 -> 2 ->3 ->..... 已有的条件&#x…

WAF相关知识及安全狗的部署和绕过

文章目录 一&#xff1a;WAF基础知识&#xff08;一&#xff09; WAF简介&#xff08;二&#xff09; WAF工作原理1&#xff09; 流量识别2&#xff09; 攻击检测3&#xff09; 攻击防御4&#xff09; 记录日志 &#xff08;三&#xff09; WAF分类&#xff08;四&#xff09; …

云原生|kubernetes|kubernetes集群部署神器kubekey的初步使用(centos7下的kubekey使用)

前言: kubernetes集群的安装部署是学习kubernetes所需要面对的第一个难关&#xff0c;确实是非常不好部署的&#xff0c;尤其是二进制方式&#xff0c;虽然有minikube&#xff0c;kubeadm大大的简化了kubernetes的部署难度&#xff0c;那么&#xff0c;针对我们的学习环境或者…

[Linux笔记]常见命令(持续施工)

常见命令 文件与目录命令 pwd 打印当前所在路径。 建议每次登录后&#xff0c;或长时间未操作时&#xff0c;进行操作前都先执行pwd以确认当前位置。 cd 进入指定目录(change direct) .当前路径 ..上级路径 windows下&#xff0c;\为路径分隔符 Linux下&#xff0c;/为路径…

4.6.tensorRT基础(1)-实际模型上onnx文件的各种操作

目录 前言1. onnx1.1 读取节点1.2 修改节点1.3 替换节点1.4 删除节点1.5 修改input和output1.6 预处理的接入 总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#…

在if/else中进行函数声明

console.log("第一次输出a: ", a) //输出 本地a if (true) {// 这里js隐式的把function a的定义放到这里来了&#xff0c;此刻这里有一个 块aa 1 // 将 块a的值 由函数修改为1console.log("第二次输出a: ",a) // 此时输出的是 块a的值function a() {} // …

【Kubernetes运维篇】RBAC之准入控制器详解

文章目录 一、ResourceQuota准入控制器1、ResourceQuota是什么&#xff1f;2、限制CPU、内存、Pod数量、Deployment数量3、限制存储空间大小 二、LimitRanger准入控制器1、LimitRanger是什么&#xff1f;2、LimitRanger限制案例 一、ResourceQuota准入控制器 中文官方参考文档…