Docker实战08|Docker管道及环境变量识别

上一篇文章中,讲解了如何通过Go语言实现对Docker Cgroup的资源限制

具体文章可见《Docker就应该这么学-07》

有需要的小伙伴可以回顾一下。

接下来本文会详细介绍一下Docker 管道及环境变量识别

管道及环境变量识别

获取代码

git clone https://gitee.com/mjreams/docker.git

当在Linux上创建两个进程时,进程之间的通信一般就会使用管道的机制。所谓管道,就是一个连接两个进程的通道,它是Linux支持IPC的其中一种方式。一般来说,管道都是半双工的,一端进行写操作,另外一端进行读操作。

常用的管道分为两种类型。一种类型是无名管道,它一般用于具有亲缘关系的进程之间;另外一种是有名管道,或者叫FIFO管道,它是一种存在于文件系统的管道,可以被两个没有任何亲缘关系的进程进行访问。有名管道一般可以通过mkfifo()函数来创建。

从本质上来说,管道也是文件的一种,但是它和文件通信的区别在于,管道有一个固定大小的缓冲区,大小一般是4KB。当管道被写满时,写进程就会被阻塞,直到有读进程把管道的内容读出来。同样地,当读进程从管道内拿数据的时候,如果这时管道的内容是空的,那么读进程同样会被阻塞,一直等到有写进程向管道内写数据。

首先增加了一个函数,使用Go提供的pipe方法生成一个匿名管道。这个函数返回两个变量,一个是读一个是写,其类型都是文件类型。

container/container_process.go
Docker实战08|Docker管道及环境变量识别_第1张图片

这个方法的改动点己经表明,这里主要解决的问题是如何将创建的管道的一端传给子进程。这是一个文件类型,肯定不能通过字符参数的方式进行传递,因此使用了command的cmd.ExtraFiles方法。这个属性的意思是会外带着这个文件句柄去创建子进程。为什么叫“外带着”呢?因为1个进程默认会有3个文件描述符,分别是标准输入、标准输出、标准错误。这3个是子进程一创建的时候就会默认带着的,那么外带的这个文件描述符理所当然地就成为了第4个。

Docker实战08|Docker管道及环境变量识别_第2张图片
这里可以看到默认的文件描述符。通过这种方式,就把管道的一端传给子进程了。下面来看子进程的改动。

container/init.go

Docker实战08|Docker管道及环境变量识别_第3张图片
这里得到父进程传递过来的管道一端后,就直接去读,由于此时父进程可能还没写入,所以此时的读操作就会停在这里等待输入。然后,看一下最终的init方法做了什么。

Docker实战08|Docker管道及环境变量识别_第4张图片
可以看到,init进程读取了父进程传递过来的参数后,在子进程内进行了执行,这样就完成了将用户指定命令传递给子进程的操作。

最后,来看一下父进程是在哪里发送的参数。

run.go Run()

	//发送用户命令
	sendInitCommand(comArray, writePipe)

在父进程中,当进程start完毕后才发送参数,也就是说,子进程这时应该己经在读等待了。

Docker实战08|Docker管道及环境变量识别_第5张图片

你可能感兴趣的:(Go,Docker,docker,java,容器)