【协作式原创】自己动手写docker之run代码解析
预备知识: Linux命令
预备知识:namespace和cgroup(CentOS7.7)
一,exec替换进程映像
函数功能: 用exec函数可以把当前进程替换为一个新进程,且新进程与原进程有相同的PID
例如:在shell命令行执行ps命令,实际上是shell进程调用fork复制一个新的子进程,在利用exec系统调用将新产生的子进程完全替换成ps进程。
- MNT namespace的go代码实现
启动一个bash进程,并且单独给予和父进程不同的mount namespace.
func main() {
cmd := exec.Command("/bin/sh") // 加载可执行文件/bin/sh到内存中并运行。
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWNS,
}
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Printf("Run error:%v\n", err)
log.Fatal(err)
}
}
- 对应如下代码
构造一个命令,用于启动init进程。
func NewParentProcess(command string, tty bool) *exec.Cmd {
args := []string{"init", command}
cmd := exec.Command("/proc/self/exe", args...) // 指向同一个可执行文件。
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS |
syscall.CLONE_NEWNET | syscall.CLONE_NEWIPC,
}
if tty {
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
}
return cmd
}
urfave cli预备知识
准备工作
- 阿里云抢占式实例:centos7.4
- 每次实例释放后都要重新安装go
wget https://dl.google.com/go/go1.13.4.linux-amd64.tar.gz
sudo tar -C /usr/local -xf go1.13.4.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
source ~/.bash_profile
yum -y install nano
yum install git
git clone https://github.com/yudidi/go-docker.git
git branch -all
git checkout remotes/origin/ns
demo
理解为什么增加init命令和为什么挂载proc
1_no_proc
2_add_proc
3_add_proc_and_not_affect_host


demo-init源码
syscall.Exec启动进程和os/exec.Command启动进程的区别
Q: run和init到底启动了几个进程
A: 2个进程,一个运行go-docker run,一个运行go-docker init。

这些进程的ns
13864和父进程3911,1号进程均一致
13868和父进程13864不同

kill掉13864,不会影响13864的运行(这就是容器内的第一个进程)
[root@192 go-docker]# kill 13864
//
[root@192 go-docker]# ps -ef|grep 138
root 13868 1 0 10:27 pts/0 00:00:00 /proc/self/exe init /bin/sh
root 13962 1323 0 10:50 pts/1 00:00:00 grep --color=auto 138
// 13868进程仍在继续打印时间
所以13864进程不表示容器(杀死了他,子进程仍在打印时间,说明这两个进程没有依赖关系),容器本身就不是一个进程,容器只是描述一种边界,而ns就是实现这个边界的方法。
ns这个空间中,13864是第一个在该空间运行的进程。踩坑
[root@192 go-docker]# ./go-docker run --ti /bin/sh
{"level":"fatal","msg":"fork/exec /proc/self/exe: no such file or directory","time":"2020-03-06T08:24:23-05:00"}
原因: // TODO
运行之后关闭之后,centos的/proc就没有了
问题的原理
- Shared subtrees
https://segmentfault.com/a/1190000006912742
https://www.cnblogs.com/sparkdev/p/9424649.html
解决: mount -t proc proc /proc
demo-ns源码
main.go
package main
import (
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"os"
)
const usage = `go-docker`
func main() {
app := cli.NewApp()
app.Name = "go-docker"
app.Usage = usage
app.Commands = []cli.Command{
runCommand,
initCommand,
}
app.Before = func(context *cli.Context) error {
logrus.SetFormatter(&logrus.JSONFormatter{})
logrus.SetOutput(os.Stdout)
return nil
}
if err := app.Run(os.Args); err != nil {
logrus.Fatal(err)
}
}
参考
【协作式原创】自己动手写docker之run代码解析的更多相关文章
- 《自己动手写docker》之namespace部门实验
动手写一遍,印象不一样! package main import ( "log" "os" "os/exec" "syscall& ...
- 【协作式原创】查漏补缺之Go并发问题(单核多核)
主要回答一下几个问题 1.单核并发问题 2.多核并发问题 2.几个不正确的同步案例 1.单核并发问题 先看一段go(1.11)代码: 单核CPU,1万个携程,每个携程执行100次+1操作, 思考n最终 ...
- 【协作式原创】查漏补缺之Go的slice基础和几个难点
[转载]队友博客 Q: 为啥要字节对齐的 https://www.nowcoder.com/discuss/57978 TODO: Q: go反汇编指令 go tool compile -S plan ...
- 【协作式原创】查漏补缺之乐观锁与悲观锁TODO
面试官:你了解乐观锁和悲观锁吗? 乐观锁和悲观锁是两种思想,用于解决并发场景下的数据竞争问题. 悲观锁的实现方式是加锁,加锁既可以是对代码块加锁(如Java的synchronized关键字),也可以是 ...
- 【协作式原创】查漏补缺之Golang中mutex源码实现(预备知识)
预备知识 CAS机制 1. 是什么 参考附录3 CAS 是项乐观锁技术,当多个线程尝试使用 CAS 同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是 ...
- 【协作式原创】查漏补缺之Golang中mutex源码实现
概览最简单版的mutex(go1.3版本) 预备知识 主要结构体 type Mutex struct { state int32 // 指代mutex锁当前的状态 sema uint32 // 信号量 ...
- 自己动手写一个编译器Tiny语言解析器实现
然后,上一篇文章简介Tiny词法分析,实现语言.本文将介绍Tiny的语法分析器的实现. 1 Tiny语言的语法 下图是Tiny在BNF中的文法. 文法的定义能够看出.INNY语言有以下特点: 1 程序 ...
- 【原创】自己动手写工具----XSmartNote [Beta 3.0]
一.前面的话 在动笔之前,一直很纠结到底要不要继续完成这个工具,因为上次给它码代码还是一年多之前的事情,参考自己动手写工具----XSmartNote [Beta 2.0],这篇博文里,很多园友提出了 ...
- 【原创】自己动手写控件----XSmartNote控件
一.前面的话 在上一篇博文自己动手写工具----XSmartNote [Beta 3.0]中,用到了若干个自定义控件,其中包含用于显示Note内容的简单的Label扩展控件,用于展示标签内容的labe ...
随机推荐
- Bugku-CTF之PHP_encrypt_1(ISCCCTF) [fR4aHWwuFCYYVydFRxMqHhhCKBseH1dbFygrRxIWJ1UYFhotFjA=]
Day34 PHP_encrypt_1(ISCCCTF) fR4aHWwuFCYYVydFRxMqHhhCKBseH1dbFygrRxIWJ1UYFhotFjA= 下载下来.zip文件
- Chrom Develop Extensions
Chrome插件 Extensions are small software programs that customize the browsing experience. They enable ...
- [爬坑记录] Qt 代码卡住 不发信号 不触发槽
先让我激动一会儿 [捂脸] 最近在用Qt做个程序 用来参加比赛 期间总共遇到两次如标题的问题 也即是 莫名其妙的不触发槽函数了 而且原因也不一样 {先说明 我学习Qt依旧只是入门级 也许入不了大佬法眼 ...
- mysql学习笔记(四):group by,limit,to_days(),from_days()
1. [Err] 1055 - Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated co ...
- awk函数实现将点分式形式的掩码转换为十进制形式的掩码
在用awk处理文本时,需要将源数据为点分式形式的掩码转换为十进制形式的掩码,下边的函数可简单实现: 转换功能函数cdr2mask function cdr2mask(mask_point) { num ...
- MindManager安装、激活
MindManager安装 MindManager激活
- VSCode的安装和使用
VSCode的安装和使用 1.先到下载地址选择适合自己系统的VSCode安装软件 https://code.visualstudio.com/#alt-downloads 以上分别是Windows , ...
- js 设计模式:观察者和发布订阅模式
总是把这两个当作同一个模式,但其实是不太一样的,现在重温一下. 观察者模式 观察者直接订阅目标,当目标触发事件时,通知观察者进行更新 简单实现 class Observer { constructor ...
- JS高级---体会面向对象和面向过程的编程思想
体会面向对象和面向过程的编程思想 ChangeStyle是自定义的构造函数,再通过原型添加方法的函数. 实例化对象,导入json参数,和创建cs,调用原型添加的方法函数 过渡,先熟悉记忆 <!D ...
- JenKins docker 集群
//tag 桉树有时间来搞 **阿斯蒂 啊 阿斯蒂