这一章看的比较混乱,可能是因为例子少;再有就是,这一章就是一个铺垫的章节。

9.2 terminal logins

  啥叫termnial? 我感觉书上的terminal指的更可能是一些物理设备(keyboard, modem这类的)

  /etc/ttys里面存着这些终端,一行代表一个终端的信息。

  限于基础知识有限,上面的内容可能理解的有误,但是对于terminal logins有一点是可以确定的:计算机事先知道有多少terminals可以logins。

  其中BSD Terminal Logins是重点讲述的,其主要流程如下流程如下:

    init (process ID 1)

    ⬇️ fork once per terminal;creates empty environment

    init

    ⬇️ each child execs getty

    getty

    ⬇️ opens terminal device; real user name; initial environment set;

    login

    ⬆️

    ⬇️  file descriptor 0 1 2

    terminal device driver

    ⬆️

    ⬇️  hard-wired connection

    user at a terminal

  在上面的过程中,可以看到Chapter 8 中fork exec的作用。

(1)先看到getty(包括getty)发生了什么

  environment:init给getty的还是一个empty environment;getty自己create了一个environment再传给login,这个时候environment中就已经包含了terminal的信息了(如TERM)。

  open terminal device: 打开terminal device,设定file descriptor 0 1 2 (input、output、error)

  read user name: output类似“login:”等着用户输入

  可以用下面的内容来理解getty:

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

  最后getty调用了login program

(2)再看login做了哪些事情

  a. 获取密码,校验密码。

  b. 转换到这个用户的home路径

  c. 把terminal device的ownship转换给用户

  d. 设定groupid

  e. ...

9.3 Network Logins

  与terminal logins不同的是,计算机事先是不知道有多少,那些,谁,要network logins的。

  因此,没有像/etc/ttys一行的terminal配置文件可以读。怎么办呢?这就要用一种类似service的方式去处理。

  为了能够最终统一处理terminal和network的logins,unix系统中存在一种pseudo terminal的机智,可以翻译为虚拟终端。

  为什么要有虚拟终端呢?

  我觉得有两个原因:

  1)作为终端用户,个人习惯来说,远程网络操作和terminal操作不希望有啥不同

  2)作为unix系统,既然已经开发了terminal logins的程序,自然希望network logins的程序也能复用terminal logins的处理程序。因为二者除了登入的方式不同,一旦与系统发生交互,处理的内容都是类似的。

  因此,pseudo terminal就出现了,完成了上述的诉求。即使从network logins的,只要login完成了,与terminal的操作并无两样。

  下面只需要关注如何产生pseudo terminal的,流程如下。

                        init process ID 1

TCP connection request from TELNET client → ⬇️ executes the shell script /etc/rc

                        inetd

                        ⬇️ fork (when connection request arrives from TELNET client)

                        inetd

                        ⬇️

                        telnetd

                        ⬇️

                        pseudo terminal device

                        ⬇️ fork

                        parent process : handle the communication across the network connection

                        child process : does an exec of the login program

                        parent & child connected through the pseudo terminal

                        child process

                        ⬆️

                        ⬇️

                        login shell

  上述的过程就是:

    在系统的start-up阶段,init会执行一个/etc/rc的shell script,这个脚本的目的是启动inetd daemons。

    随后,inetd daemons就一直等着,直到有来自telnet client的请求就fork出去一个小弟inetd去处理这个请求。

    这个inetd小弟处理请求的方式是执行TELNET server,即telnetd。

    随后telnetd随即打开一个pseudo terminal device,并且用fork的方式一分为二:

      parent process : 负责管network connection的事情

      child process : 负责管执行login相关的东西

      parent 与 child 之间通过pseudo terminal来关联

9.4 Process Group

   一堆process组成一个process group,猜测有process group是为了方便集体对某种类型的process进行集体操作。不细说。

9.5 Sessions

   多个process groups构成了Session。

9.8 Job Control

  这一部分书上有个了例子,从结果来看:不带job control的shell,一个terminal只能产生一个PGID;带job control的shell,一个terminal可以产生好几个PGID.

9.10 Orphaned Process Groups

  由于缺乏后面signal的知识,就只看9.12这个代码。

  代码不复杂,这里不详细记录了。

  只说让我疑惑的地方。

...
signal(SIGHUP, sig_hup);
kill(getpid(), SIGTSTP);
...

  源代码中有这么两行,是在fork后的child process中执行的。

  先放着signal不管,这个kill就比较让人看着不好理解:都kill了,为什么child process后面的语句还能执行呢?

  先man 2 kill一下:“kill - send signal to a process”。这才知道,kill做的事情是发送一个信号

  那么再看一下发送的这个信号SIGTSTP是啥意思呢?

  书上有这么一段话:“Unfortunately, the term stop has different meanings.....Therefore, the terminal driver calls the character that generates the interactive stop signal the suspend character, not the stop character”。

  可以理解为:这里的stop并不是说直接给弄没了,而是先让这个进程等着的意思。

  再回来看signal。

  源代码中故意弄没了parent process,留着child process,这样就造成了orphaned process group的情况。按照系统的要求,对于orphaned process group中的所有的余留的进程,都会被发送一个hang-up的信号(SIGHUP),随后伴随着就SIGCONT的信号。signal这个语句就是为了能让child process接收到SIGHUP这个信号,并继续执行下去。

  通过这个事情,这个kill跟他原来的意思还是差挺多的,还是要多注意一些。

  

     

  

  

  

最新文章

  1. 上个项目的一些反思 I
  2. CISA 信息系统审计知识点 [第二章. IT治理和管理 ]
  3. Javascript 弱类型:除法结果是小数
  4. 安装CMS遇到php5.3的问题
  5. WPF中的DependencyProperty存储方式详解
  6. Python-aiohttp百万并发
  7. [iOS UI进阶 - 6.1] 核心动画CoreAnimation
  8. 初识AOP与动态代理
  9. 即时通讯软件openfire+spark+smack
  10. Java反射之调用内部类
  11. mysql千万级大数据SQL查询优化
  12. Ambari 常用的 REST API 介绍
  13. KMP性质小结
  14. android 工具库
  15. vue-router拦截
  16. Future模式介绍及入门使用
  17. 如何将项目连接数据库(连接mysql)
  18. python爬虫学习(一):BeautifulSoup库基础及一般元素提取方法
  19. 5210: 最大连通子块和 动态DP 树链剖分
  20. 在Java API设计中,面向接口编程的思想,以及接口和工厂的关系

热门文章

  1. nodejs封装的webget webpost方法
  2. 【JavaScript 封装库】BETA 1.0 测试版发布!
  3. EF写in
  4. 【BZOJ4555】[TJOI2016&HEOI2016] 求和(NTT)
  5. 【转】Android开发学习笔记(一)——初识Android
  6. 2018.7.22 Jdom与dom的区别
  7. javascript中的作用域与作用域链
  8. JQuery 过滤选择器 与属性修改的方法演示比较
  9. iOS程序猿如何快速掌握 PHP,化身"全栈攻城狮"?
  10. link链接外部样式表