【协作式原创】自己动手写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 ...
随机推荐
- 概率dp lightoj 1342
题意:有N根木棍,每根木棍都有一个权值 其中有若干根可识别,若干根不可识别的,抽到了可识别的棍子,就不放回,抽到了不可识别的,就要放回 ,问所有棍子都至少被抽过一次后权值和的期望 不可识别的棍子,就相 ...
- 关于AutoCompleteTextView的用法:根据输入的自动匹配关键词
- Ansible - playbook - 概要
概述 简单描述 ansible playbook 1. playbook 概述 ansible 的 "脚本" 场景 ansible 单条命令, 执行一个操作 问题 如果执行多个操作 ...
- 【C语言】分别用下标法,地址法和指针法输出数组中的全部元素
#include<stdio.h> int main() { ] = { ,,,, }; int i, * p; printf("下标法:\n"); ; i < ...
- python报错使用yum命令报错File "/usr/bin/yum", line 30 except KeyboardInterrupt, e: SyntaxError: invalid syntax问题
参考链接:https://blog.csdn.net/ltz150/article/details/77870735 1.背景: CentOS 7升级Python到3.6.2后,需要在/usr/bin ...
- Gitee 码云 pages 搭建vue项目记录
首先要在.gitignore文件去掉/dist,这个文件默认是不上传的,但是执行打包bulid的时候会生成dist文件,而线上访问的是打包之后的dist文件: vue.config.js文件,如下图箭 ...
- opencv:绘制图像直方图
#include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace st ...
- The Preliminary Contest for ICPC Asia Xuzhou 2019 E XKC's basketball team(排序+二分)
这题其实就是瞎搞,稍微想一想改一改就能过. 排序按值的大小排序,之后从后向前更新node节点的loc值,如果后一个节点的loc大于(不会等于)前一个节点的loc,就把前一个节点的loc值设置为后面的l ...
- 用svn客户端checkout时报错RA layer request failed
用svn客户端checkout时报错: RA layer request failedsvn: Unable to connect to a repository at URL 'https://30 ...
- EntityFramework中使用sql语句
https://blog.csdn.net/yangyangafan/article/details/77602133 EntityFramework操作数据库谜一般的方便还不用写数据库,但前提是很简 ...