runc 端解析:

1、 runc/utils_linux.go

func (r *runner) run(config *specs.Process) (int , error)

在该函数中第一次对容器的IO进行了处理,首先调用tty, err := setupIO(process, rootuid, rootgid, r.console, config.Terminal, r.detach, || r.create),创建并返回了一个结构tty,tty的具体类型如下所示:

type tty struct {

  console  libcontainer.Console

  state    *term.State
  closers  []io.Closer
  postStart []io.Closer   wg    sync.WaitGroup 
}

之后又有handler := newSignalHandler(tty, r.enableSubreaper)以及tty.ClosePostStart(), status, err := handler.forward(process)对tty进行处理(主要是针对winsize)。同时,我们可以发现在handler.forward函数之前有对r.detach进行判断,若r.detach为true则直接返回了。

2、runc/utils_linux.go

// setupIO sets the proper IO on the process depending on the configuration

// detach and createTTy will not work unless a console path is passed  --->即detach 和createTty不能同时为true,除非console不为空

func setupIO(process *libcontainer.Process, rootuid, rootgid int, console string, createTTY, detach bool) (*tty, error)

(1)当createTTy为true时,调用 return createTty(process, rootuid, rootgid, console) ---> 要求tty,则优先创建tty

(2)当detach为true时,调用dupStdio(process, rootuid, rootgid), 最后再返回一个空的tty, return &tty{}

(3)当createTTy和detach都为false时,则return createStdioPipes(process, rootuid, rootgid)

------------------------------------------------------------  tty方式 ----------------------------------------------------

3、runc/tty.go

func createTty(p *libcontainer.Process, rootuid, rootgid int, consolePath string) (*tty, error)

(1)当用户指定了consolePath的时候,则直接调用p.consoleFromPath(consolePath),再返回一个空的tty, return &tty{}

(2)当用户未指定consolePath时,则调用console, err := p.NewConsole(rootuid, rootgid)创建一个新的console,并且将标准输入输出与console相连。接着调用state, err := term.SetRawTerminal(os.Stdin.Fd())函数将标准输入设置为raw mode。最后返回:

return &tty {

  console:  console,
  state:   state,
  closers:  []io.Closer{
    console,
  }, }

  

4、runc/libcontainer/process.go

// ConsoleFromPath sets the process's console with the path provided

func (p *Process) ConsoleFromPath(path string) error

仅仅只是将path赋值给p.consolePath

5、runc/libcontainer/console_linux.go

// NewConsole returns an initialized console that can be used within a container by copying bytes

// from the master side to the slave that is attached as the tty for the container's init process

func NewConsole(uid, gid int) (Console, error)

首先调用master, err := os.OpenFile("/dev/ptmx", syscall.O_RDWR | syscall.O_NOCTTY|syscall.O_CLOEXEC, 0),打开主设备,接着调用console, err := ptsname(master)获取从设备的设备名,之后再对主从设备进行一系列的操作。最后,return &linuxConsole{ slavePath: console, master: master}

------------------------------------------------------------------------ detach 模式---------------------------------------------------------------

6、runc/utils_linux.go

func dupStdio(process *libcontainer.Process, rootuid, rootgid int) error

该函数的操作很简单,就是直接将标准IO,os.Stdin, os.Stdout, os.Stderr和process的Stdin, Stdout, Stderr相连,然后改变这几个文件描述符的uid和gid即可。

--------------------------------------------------------------------------- 不分配terminal,不detach ------------------------------------------

7、runc/tty.go

// setup standard pipes so that the TTY of the calling runc process is not inherited by the container

func createStdioPipes(p *libcontainer.Process, rootuid, rootuid int) (*tty, error)

首先调用i, err := p.InitializeIO(rootuid, rootgid),其中函数InitializeIO函数做的工作其实就是创建了三个管道,并将一端连接process的STDIO,再将另一端返回给i。接着对tty 结构进行填充,主要将STDIO赋值给tty.Closers和tty.postStart。最后将i和os.StdIO相连。

容器内解析:

1、runc/libcontainer/standard_init_linux.go

func (l *linuxStandardInit) Init() error

该函数先判断从runc端传来的配置中l.config.Console是否为空,如果不为空,则调用console = newConsoleFromPath(l.config.Console),获取一个linuxConsole的实例,其中只将slavePath字段设置为l.config.Console。之后,再调用console.dupStdio(),在dupStdio中打开SlaveConsole文件,并且将fds 复制到当前进程的stdio。如果console不为空,则调用system.Setctty()。在Setctty()中,只是简单地调用了函数,syscall.RawSyscall(syscall.SYS_IOCTL, 0, uintptr(syscall.TIOCSCTTY), 0)

2、runc/libcontainer/console_linux.go

// newConsoleFromPath is an internal function returning an initialized console for use inside a container's MNT namespace

func newConsoleFromPath(slavePath) *linuxConsole

只是简单地返回 return &linuxConsole{ slavePath: slavePath}

3、 runc/libcontainer/console_linux.go

// dupStdio opens the slavePath for the console and dups the fds to the current processes stdio, fd 0, 1, 2

func (c *linuxConsole) dupStdio() error

(1)、首先打开console: slave, err := c.open(syscall.O_RDWR),再调用fd := int(slave.Fd())转换为文件描述符

(2)、最后,调用syscall.Dup3()将STDIO绑定到console上

4、runc/libcontainer/system/linux.go

func Setctty() error

该函数只是简单地调用了syscall.RawSyscall(syscall.SYS_IOCTL, 0, uintptr(syscall.TIOCSCTTY), 0)

runc的detach, console, tty等相关问题的更多相关文章

  1. tty/pts 相关指令

    http://unix.stackexchange.com/questions/136662/how-can-we-know-whos-at-the-other-end-of-a-pseudo-ter ...

  2. Linux TTY介绍

    1. TTY介绍 TTY(TeleType)指Linux中的一类终端(Terminal)设备, 是一种字符设备 在Linux中, tty可分为如下几类- 串行端口终端(serial port term ...

  3. console对象

    今天无意中看到console.info()的时候不自觉的楞了一下,对于console.info()确实不是十分的了解,平时就是用console.log(),既然不太明白就去网上看了一下关于consol ...

  4. Chrome开发者工具详解(1)-Elements、Console、Sources面板

    Chrome开发者工具详解(1)-Elements.Console.Sources面板 Chrome开发者工具面板 面板上包含了Elements面板.Console面板.Sources面板.Netwo ...

  5. Chrome开发者工具详解(1):Elements、Console、Sources面板

    Chrome开发者工具面板 面板上包含了Elements面板.Console面板.Sources面板.Network面板. Timeline面板.Profiles面板.Application面板.Se ...

  6. Node.js小白开路(一)-- console篇

    在所有内容的学习之中我们经常首先要接受到的常常很大一部分为命令行或是工具的内容展示,console内容为node.js在命令行中答应数据内容的一个途径. Console是nodejs中的元老级模块了. ...

  7. BOM相关知识点

    1.BOM概念:Browser Object Model 浏览器对象模型作用:提供了使用JS操作浏览器的接口 2.BOM包含了许多对象信息,包括如下这些:(1)screen 屏幕信息(2)locati ...

  8. linux 终端下敲ctrl-c时,到底发生了什么?(转)

    通过telnet登录到单板,然后按ctrl-c会发生什么情况,流程是怎么样的? 在分析之前,先介绍tty的相关知识.我们可以认为,所有跟输入输出相关的操作,最终都由tty来接管.举例来说,当我们敲 l ...

  9. Openstack Basic

    html,body { } .CodeMirror { height: auto } .CodeMirror-scroll { } .CodeMirror-lines { padding: 4px 0 ...

随机推荐

  1. 根据IP地址获取地址所在城市帮助类(IPHelper)

    很多类库都是需要在长时间的编写过程中进行积累的,进入软件编程行业已经是第五个年头了,从2011年写下第一行代码到现在不知道已经写了多少行代码了,时间也过得挺快的.最近事情比较多,也很少写博客了,最近项 ...

  2. js 自带的 reduce() 方法

    1.方法说明 , Array的reduce()把一个函数作用在这个Array的[x1, x2, x3...]上,这个函数必须接收两个参数,reduce()把结果继续和序列的下一个元素做累积计算,其效果 ...

  3. GWYAlertSelectView 选择收货地址和选择联系人

    iOS 开发在app内(特别是在类似购物和旅游类)经常会用到选择,添加联系人和收货地址,而且经常都是在跳转界面,很是麻烦,今天我就自己封装了一个类似弹出视图的代码,方便了很多!demo地址: http ...

  4. K3Cloud开放数据模型

          金蝶K/3 Cloud是基于WEB2.0与云技术的一个开放式.社会化的新时代企业管理服务平台.整个产品采用SOA架构,完全基于BOS平台组建而成,业务架构上贯穿流程驱动与角色驱动思想,结合 ...

  5. 微软发布ASP.NET 5路线图

    这次随 Visual Studio 2015 发布的 ASP.NET 版本是 ASP.NET 4.6 与 ASP.NET 5 beta5.在 VS2015 发布的同时,微软也发布了 ASP.NET 5 ...

  6. cl_gui_cfw=>dispatch

    将已经触发的EVENT发送给他们各自的EVENT HANDLER,以便让这些事件得到响应. 根据返回值可以判断是否发送成功. CALL METHOD cl_gui_cfw=>dispatch   ...

  7. IOS 杂笔-4(属性与成员变量的区别)

    属性可以用点语法,比如self.xxx,在外部调用也同样可以someClass.xxx. 属性实际上是对一组set和get方法的简单封装(oc的get方法没有get前缀),同样会自动生成一个私有的成员 ...

  8. 使用 SharedPreferences 实现数据的存储和读取

    在开发的过程中我们必须遇到的就是如何对用户的数据进行有效的存储以及读取.我们举个例子,现在我们使用app,当我们登陆一个账号的时候选择记住密码软件就会记住我们的账号以及密码,我们退出当前账号,就可以直 ...

  9. IOS之UI -- 按钮UIButton的细节

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  10. Java基础之子类父类属性覆盖

    当java的子类和父类具有相同名字的属性时,到底java是怎么处理的. 先看代码: package com.joyfulmath.study.field; public class Person { ...