runc源码分析
runc代码目录结构
├── create.go # createCommand
├── delete.go # deleteCommand
├── events.go # eventsCommand
├── exec.go # execCommand
├── features.go # featuresCommand
├── kill.go # killCommand
├── libcontainer # 核心实现逻辑
├── list.go # listCommand
├── main.go # main函数
├── pause.go # pauseCommand
├── ps.go # psCommand
├── restore.go # restoreCommand
├── run.go # runCommand
├── spec.go # specCommand
├── start.go # startCommand
├── state.go # stateCommand
├── update.go # updateCommand
├── utils_linux.go # startContainer
libcontainer目录结构
libcontainer
├── apparmor
├── capabilities
├── cgroups
├── configs
├── console_linux.go
├── container.go
├── container_linux.go
├── container_linux_test.go
├── criu_opts_linux.go
├── devices
├── error.go
├── factory_linux.go
├── factory_linux_test.go
├── init_linux.go
├── integration
├── intelrdt
├── keys
├── logs
├── message_linux.go
├── mount_linux.go
├── network_linux.go
├── notify_linux.go
├── notify_linux_test.go
├── notify_v2_linux.go
├── nsenter
├── process.go
├── process_linux.go
├── restored_process.go
├── rootfs_linux.go
├── rootfs_linux_test.go
├── seccomp
├── setns_init_linux.go
├── specconv
├── standard_init_linux.go
├── state_linux.go
├── state_linux_test.go
├── stats_linux.go
├── sync.go
├── system
├── user
├── userns
└── utils
Main函数
runc的代码仓库主要使用了github.com/urfave/cli的命令框架(该框架与cobra命令框架类似)。添加了多个重要的子命令。
func main() {
app := cli.NewApp()
app.Name = "runc"
app.Usage = usage
app.Commands = []cli.Command{
checkpointCommand,
createCommand,
deleteCommand,
eventsCommand,
execCommand,
killCommand,
listCommand,
pauseCommand,
psCommand,
restoreCommand,
resumeCommand,
runCommand,
specCommand,
startCommand,
stateCommand,
updateCommand,
featuresCommand,
}
runCommand
以runCommand
为例分析子命令的调用流程。
github.com/urfave/cli命令框架代码格式:
创建一个Command结构体,包含:
-
Name:命名名称
-
Usage:使用说明
-
Description:描述命令信息
-
Flags:解析参数
-
Action: command run的核心逻辑。
// default action is to start a container
var runCommand = cli.Command{
Name: "run",
Usage: "create and run a container",
// 删除描述信息
ArgsUsage: ``,
Description: ``,
Flags: []cli.Flag{
cli.StringFlag{
Name: "bundle, b",
Value: "",
Usage: `path to the root of the bundle directory, defaults to the current directory`,
},
// 删除多余的FLAG代码
},
Action: func(context *cli.Context) error {
if err := checkArgs(context, 1, exactArgs); err != nil {
return err
}
// 核心代码,启动容器
status, err := startContainer(context, CT_ACT_RUN, nil)
if err == nil {
// exit with the container's exit status so any external supervisor is
// notified of the exit with the correct exit status.
os.Exit(status)
}
return fmt.Errorf("runc run failed: %w", err)
},
}
startContainer
启动容器的流程:
-
setup spec信息。
-
基于spec信息创建container。
-
通过runner启动进程。
删除error处理代码
func startContainer(context *cli.Context, action CtAct, criuOpts *libcontainer.CriuOpts) (int, error) {
if err := revisePidFile(context); err != nil {
return -1, err
}
spec, err := setupSpec(context)
id := context.Args().First()
notifySocket := newNotifySocket(context, os.Getenv("NOTIFY_SOCKET"), id)
if notifySocket != nil {
notifySocket.setupSpec(spec)
}
container, err := createContainer(context, id, spec)
if notifySocket != nil {
if err := notifySocket.setupSocketDirectory(); err != nil {
return -1, err
}
if action == CT_ACT_RUN {
if err := notifySocket.bindSocket(); err != nil {
return -1, err
}
}
}
// Support on-demand socket activation by passing file descriptors into the container init process.
listenFDs := []*os.File{}
if os.Getenv("LISTEN_FDS") != "" {
listenFDs = activation.Files(false)
}
r := &runner{
enableSubreaper: !context.Bool("no-subreaper"),
shouldDestroy: !context.Bool("keep"),
container: container,
listenFDs: listenFDs,
notifySocket: notifySocket,
consoleSocket: context.String("console-socket"),
detach: context.Bool("detach"),
pidFile: context.String("pid-file"),
preserveFDs: context.Int("preserve-fds"),
action: action,
criuOpts: criuOpts,
init: true,
}
return r.run(spec.Process)
}
待完善
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.
最后修改 June 11, 2025: update k8s (3e78c6a)