构建容器
linux proc 文件系统
linux下的/proc
文件系统是由内核提供的,它其实不是一个真正的文件系统,只是包含了系统运行时的信息(比如系统内寻、mount设备信息、一些硬件配置等),它只存在于内存中,而不占用外存空间。它以文件系统的方式,为访问内核数据的操作提供借口。实际上,很多系统工具都是简单地去读取这个文件系统的某个文件内容, 比如lsmod
= cat /proc./modules
当遍历这个目录的时候,会发现很多数字,这些都是为每个进程创建的空间,数字就是它们的 PID 。
下面介绍几个比较重要的的部分
PATH | 作用 |
---|---|
/proc/N | PID为N的进程 |
/proc/N/cmdline | 进程启动命令 |
/proc/N/cwd | 链接带进程当前工作目录 |
/proc/N/environ | 进程环境变量列表 |
/proc/N/exe | 链接到进程的执行命令文件 |
/proc/N/fd | 包含进程相关的所有文件描述符 |
/proc/N/maps | 与进程相关的内存映射信息 |
/proc/N/mem | 指代进程持有的内存,不可读 |
/proc/N/root | 链接到进程的根目录 |
/proc/N/stat | 进程的状态 |
/proc/N/statm | 进程使用的内存状态 |
/proc/N/status | 进程状态信息, 比stat/statm 更具可读性 |
/proc/self | 链接到当前正在运行的进程 |
const usage = `docker-ece is a simple container runtiome implementation.
The purpose of this project is to learn how docker works and how to
write a docker by ourselves. Enjoy it just for fun`
func main() {
app := &cli.App{
Name: "docker-ece",
Usage: usage,
}
app.Commands = []*cli.Command{
&initCommand,
&runCommand,
}
app.Before = func(context *cli.Context) error {
log.SetFormatter(&log.JSONFormatter{
})
log.SetOutput(os.Stdout)
return nil
}
if err := app.Run(os.Args); err != nil {
log.Fatal(err)
}
}
var runCommand = cli.Command{
Name: "run",
Usage: `Create a container with namespace and cgroups limit
mydocker run -ti [command ]`,
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "ti",
Usage: "enable tty",
},
&cli.StringFlag{
Name: "mem",
Usage: "memory limit",
},
&cli.StringFlag{
Name: "cpumax",
Usage: "cpu limit",
},
//&cli.StringFlag{
// Name: "cpuset",
// Usage: "cpuset limit",
//},
},
Action: func(ctx *cli.Context) error {
if ctx.NArg() < 1 {
return errors.New("Miss container command")
}
var cmdArr []string
for _, arg := range ctx.Args().Slice() {
cmdArr = append(cmdArr, arg)
}
tty := ctx.Bool("ti")
resConf := &subsystems.ResourceConfig{
MemoryMax: ctx.String("mem"),
CpuMax: ctx.String("cpumax"),
//CpuSet: ctx.String("cpuset"),
}
// Run 准备启动容器
Run(tty, cmdArr, resConf)
return nil
},
}
var initCommand = cli.Command{
N