• gvisor gofer chroot


     

    Files in the sandbox may be backed by different implementations. For host-native files (where a file descriptor is available), the Gofer may return a file descriptor to the Sentry via SCM_RIGHTS1.

    These files may be read from and written to through standard system calls, and also mapped into the associated application’s address space. This allows the same host memory to be shared across multiple sandboxes, although this mechanism does not preclude the use of side-channels (see Security Model.

    Note that some file systems exist only within the context of the sandbox. For example, in many cases a tmpfs mount will be available at /tmp or /dev/shm, which allocates memory directly from the sandbox memory file (see below). Ultimately, these will be accounted against relevant limits in a similar way as the host native case.

    root@cloud:~# ps -elf | grep docker
    4 S root     926586      1  0  80   0 - 1392756 futex_ Jan14 ?      00:06:08 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
    0 S root     941940  22795  0  80   0 - 177146 futex_ 10:11 ?       00:00:00 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/f1663b36dc38560d1c77639273944c2da612e5c11571bdeb717d371a78b06486 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runsc-kvm
    0 S root     942946 940675  0  80   0 - 538568 futex_ 10:45 pts/0   00:00:00 docker run -it --runtime=runsc-kvm --rm debian /bin/bash
    0 S root     942983  22795  0  80   0 - 177146 futex_ 10:45 ?       00:00:00 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/13802c34815d499799af132ae792b796d3cbf52b5792aa536dd756c2c6d993a0 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runsc-kvm
    4 S root     942997 942983  0  80   0 - 186593 futex_ 10:45 ?       00:00:03 runsc-gofer --root=/var/run/docker/runtime-runsc-kvm/moby --log=/run/containerd/io.containerd.runtime.v1.linux/moby/13802c34815d499799af132ae792b796d3cbf52b5792aa536dd756c2c6d993a0/log.json --log-format=json --platform=kvm --log-fd=3 gofer --bundle /run/containerd/io.containerd.runtime.v1.linux/moby/13802c34815d499799af132ae792b796d3cbf52b5792aa536dd756c2c6d993a0 --spec-fd=4 --mounts-fd=5 --io-fds=6 --io-fds=7 --io-fds=8 --io-fds=9 --apply-caps=false --setup-root=false
    4 S nobody   943010 942983  2  80   0 - 68452017770 ep_pol 10:45 pts/3 00:00:41 runsc-sandbox --root=/var/run/docker/runtime-runsc-kvm/moby --log=/run/containerd/io.containerd.runtime.v1.linux/moby/13802c34815d499799af132ae792b796d3cbf52b5792aa536dd756c2c6d993a0/log.json --log-format=json --platform=kvm --log-fd=3 boot --bundle=/run/containerd/io.containerd.runtime.v1.linux/moby/13802c34815d499799af132ae792b796d3cbf52b5792aa536dd756c2c6d993a0 --controller-fd=4 --mounts-fd=5 --spec-fd=6 --start-sync-fd=7 --io-fds=8 --io-fds=9 --io-fds=10 --io-fds=11 --device-fd=12 --stdio-fds=13 --stdio-fds=14 --stdio-fds=15 --pidns=true --cpu-num 64 13802c34815d499799af132ae792b796d3cbf52b5792aa536dd756c2c6d993a0
    0 S root     943339 940908  0  80   0 -  1418 pipe_r 11:19 pts/1    00:00:00 grep --color=auto docker
    root@cloud:~# dlv attach  942997
    (dlv) bt
    0  0x000000000008dccc in syscall.Syscall6
       at src/syscall/asm_linux_arm64.s:43
    1  0x00000000002c1ce8 in gvisor.dev/gvisor/pkg/flipcall.(*Endpoint).futexWaitConnState
       at pkg/flipcall/futex_linux.go:76
    2  0x00000000002c1b58 in gvisor.dev/gvisor/pkg/flipcall.(*Endpoint).futexWaitUntilActive
       at pkg/flipcall/futex_linux.go:56
    3  0x00000000002c08bc in gvisor.dev/gvisor/pkg/flipcall.(*Endpoint).ctrlRoundTrip
       at pkg/flipcall/ctrl_futex.go:133
    4  0x00000000002c15c4 in gvisor.dev/gvisor/pkg/flipcall.(*Endpoint).SendRecv
       at pkg/flipcall/flipcall.go:234
    5  0x00000000002e791c in gvisor.dev/gvisor/pkg/p9.(*channel).send
       at pkg/p9/transport_flipcall.go:165
    6  0x00000000002e74f8 in gvisor.dev/gvisor/pkg/p9.(*channel).service
       at pkg/p9/transport_flipcall.go:88
    7  0x00000000002ed06c in gvisor.dev/gvisor/pkg/p9.(*connState).initializeChannels.func1
       at pkg/p9/server.go:457
    8  0x0000000000077c84 in runtime.goexit
       at src/runtime/asm_arm64.s:1136
    (dlv) 
    cmd/help.go
    // Execute implements subcommands.Command.Execute.
    func (h *Help) Execute(ctx context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus {
        switch f.NArg() {
        case 0:
            fmt.Fprintf(h.cdr.Output, "Usage: %s <flags> <subcommand> <subcommand args>
    
    ", h.cdr.Name())
            fmt.Fprintf(h.cdr.Output, `runsc is the gVisor container runtime.
    Functionality is provided by subcommands. For help with a specific subcommand,
    use "%s %s <subcommand>".
    `, h.cdr.Name(), h.Name())
            h.cdr.VisitGroups(func(g *subcommands.CommandGroup) {
                h.cdr.ExplainGroup(h.cdr.Output, g)
            })
    
            fmt.Fprintf(h.cdr.Output, "Additional help topics (Use "%s %s <topic>" to see help on the topic):
    ", h.cdr.Name(), h.Name())
            for _, cmd := range h.commands {
                fmt.Fprintf(h.cdr.Output, "	%-15s  %s
    ", cmd.Name(), cmd.Synopsis())
            }
            fmt.Fprintf(h.cdr.Output, "
    Use "%s flags" for a list of top-level flags
    ", h.cdr.Name())
            return subcommands.ExitSuccess
        default:
            // Look for commands registered to the commander and print help explanation if found.
            found := false
            h.cdr.VisitCommands(func(g *subcommands.CommandGroup, cmd subcommands.Command) {
                if f.Arg(0) == cmd.Name() {
                    h.cdr.ExplainCommand(h.cdr.Output, cmd)
                    found = true
                }
            })
            if found {
                return subcommands.ExitSuccess
            }
    
            // Next check commands registered to the help command.
            for _, cmd := range h.commands {
                if f.Arg(0) == cmd.Name() {
                    fs := flag.NewFlagSet(f.Arg(0), flag.ContinueOnError)
                    fs.Usage = func() { h.cdr.ExplainCommand(h.cdr.Error, cmd) }
                    cmd.SetFlags(fs)
                    if fs.Parse(f.Args()[1:]) != nil {
                        return subcommands.ExitUsageError
                    }
                    return cmd.Execute(ctx, f, args...)
                }
            }
    
            fmt.Fprintf(h.cdr.Error, "Subcommand %s not understood
    ", f.Arg(0))
        }
    
        f.Usage()
        return subcommands.ExitUsageError
    }
    // Execute implements subcommands.Command.
    func (g *Gofer) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus {
        if g.bundleDir == "" || len(g.ioFDs) < 1 || g.specFD < 0 {
            f.Usage()
            return subcommands.ExitUsageError
        }
    
        conf := args[0].(*config.Config)
    
        specFile := os.NewFile(uintptr(g.specFD), "spec file")
        defer specFile.Close()
        spec, err := specutils.ReadSpecFromFile(g.bundleDir, specFile, conf)
        if err != nil {
            Fatalf("reading spec: %v", err)
        }
    
        if g.setUpRoot {
            if err := setupRootFS(spec, conf); err != nil {
                Fatalf("Error setting up root FS: %v", err)
            }
        }
        if g.applyCaps {
            // Disable caps when calling myself again.
            // Note: minimal argument handling for the default case to keep it simple.
            args := os.Args
            args = append(args, "--apply-caps=false", "--setup-root=false")
            if err := setCapsAndCallSelf(args, goferCaps); err != nil {
                Fatalf("Unable to apply caps: %v", err)
            }
            panic("unreachable")
        }
    
        // Find what path is going to be served by this gofer.
        root := spec.Root.Path
        if !conf.TestOnlyAllowRunAsCurrentUserWithoutChroot {
            root = "/root"
        }
    
        // Resolve mount points paths, then replace mounts from our spec and send the
        // mount list over to the sandbox, so they are both in sync.
        //
        // Note that all mount points have been mounted in the proper location in
        // setupRootFS().
        cleanMounts, err := resolveMounts(conf, spec.Mounts, root)
        if err != nil {
            Fatalf("Failure to resolve mounts: %v", err)
        }
        spec.Mounts = cleanMounts
        go func() {
            if err := g.writeMounts(cleanMounts); err != nil {
                panic(fmt.Sprintf("Failed to write mounts: %v", err))
            }
        }()
    
        specutils.LogSpec(spec)
    
        // fsgofer should run with a umask of 0, because we want to preserve file
        // modes exactly as sent by the sandbox, which will have applied its own umask.
        syscall.Umask(0)
    
        if err := fsgofer.OpenProcSelfFD(); err != nil {
            Fatalf("failed to open /proc/self/fd: %v", err)
        }
    
        if err := syscall.Chroot(root); err != nil {
            Fatalf("failed to chroot to %q: %v", root, err)
        }
        if err := syscall.Chdir("/"); err != nil {
            Fatalf("changing working dir: %v", err)
        }
        log.Infof("Process chroot'd to %q", root)
    
        // Start with root mount, then add any other additional mount as needed.
        ats := make([]p9.Attacher, 0, len(spec.Mounts)+1)
        ap, err := fsgofer.NewAttachPoint("/", fsgofer.Config{
            ROMount: spec.Root.Readonly || conf.Overlay,
        })
        if err != nil {
            Fatalf("creating attach point: %v", err)
        }
        ats = append(ats, ap)
        log.Infof("Serving %q mapped to %q on FD %d (ro: %t)", "/", root, g.ioFDs[0], spec.Root.Readonly)
    
        mountIdx := 1 // first one is the root
        for _, m := range spec.Mounts {
            if specutils.Is9PMount(m) {
                cfg := fsgofer.Config{
                    ROMount: isReadonlyMount(m.Options) || conf.Overlay,
                    HostUDS: conf.FSGoferHostUDS,
                }
                ap, err := fsgofer.NewAttachPoint(m.Destination, cfg)
                if err != nil {
                    Fatalf("creating attach point: %v", err)
                }
                ats = append(ats, ap)
    
                if mountIdx >= len(g.ioFDs) {
                    Fatalf("no FD found for mount. Did you forget --io-fd? mount: %d, %v", len(g.ioFDs), m)
                }
                log.Infof("Serving %q mapped on FD %d (ro: %t)", m.Destination, g.ioFDs[mountIdx], cfg.ROMount)
                mountIdx++
            }
        }
        if mountIdx != len(g.ioFDs) {
            Fatalf("too many FDs passed for mounts. mounts: %d, FDs: %d", mountIdx, len(g.ioFDs))
        }
    
        if conf.FSGoferHostUDS {
            filter.InstallUDSFilters()
        }
    
        if err := filter.Install(); err != nil {
            Fatalf("installing seccomp filters: %v", err)
        }
    
        runServers(ats, g.ioFDs)
        return subcommands.ExitSuccess
    }
    I0115 09:33:42.721710       1 main.go:210] Args: [runsc-gofer --root=/run/user/0/runsc --debug-log=/tmp/runsc/ --strace=true --debug-log-fd=3 gofer --bundle /mycontainer --spec-fd=4 --mounts-fd=5 --io-fds=6 --apply-caps=false --setup-root=false]
    I0115 09:33:42.721755       1 main.go:211] Version release-20201216.0-106-gc49ce8ca8ab9
    I0115 09:33:42.721775       1 main.go:212] GOOS: linux
    I0115 09:33:42.721794       1 main.go:213] GOARCH: arm64
    I0115 09:33:42.721817       1 main.go:214] PID: 1
    I0115 09:33:42.721837       1 main.go:215] UID: 0, GID: 0
    I0115 09:33:42.721857       1 main.go:216] Configuration:
    I0115 09:33:42.721876       1 main.go:217]              RootDir: /run/user/0/runsc
    I0115 09:33:42.721896       1 main.go:218]              Platform: ptrace
    I0115 09:33:42.721915       1 main.go:219]              FileAccess: 0, overlay: false
    I0115 09:33:42.721937       1 main.go:220]              Network: 0, logging: false
    I0115 09:33:42.721959       1 main.go:221]              Strace: true, max size: 1024, syscalls:
    I0115 09:33:42.721979       1 main.go:222]              VFS2 enabled: false
    I0115 09:33:42.721998       1 main.go:223] ***************************
    I0115 09:33:42.723379       1 gofer.go:164] Process chroot'd to "/root"
    I0115 09:33:42.723409       1 gofer.go:175] Serving "/" mapped to "/root" on FD 6 (ro: true)
    I0115 09:33:42.723428       1 seccomp.go:61] Installing seccomp filters for 57 syscalls (action=kill process)
    I0115 09:33:42.724207       1 seccomp.go:85] Seccomp filters installed.
    I0115 09:34:32.255208       1 gofer.go:231] All 9P servers exited.
    I0115 09:34:32.255286       1 main.go:236] Exiting with status: 0
    ~
    ~
    ~
    ~
    ~
    "/tmp/runsc/runsc.log.20210115-173342.650687.gofer" 40L, 3384C 

     文件系统读写

    Let's walk through a read operation from the application:

    1. The application running inside the sandbox issues a read(2) syscall to gVisor.
    2. gVisor looks up the FD from the read call in the task's FD table.
    3. That FD belongs to a file backed by pkg/sentry/fs/gofer.fileOperations.
    4. gofer.fileOperations.Read() is called.
    5. gofer.fileOperations checks whether it has a host FD (note that this is different from the FD in step 2 which is a virtual FD that doesn't exist in the host).
    6. If it does, it can shortcut the read and issues a read(2) syscall to the host.
    7. If it doesn't, then it issues a 9P read call to the gofer.
    root@cloud:~# docker run -it --runtime=runsc-kvm  -v share:/share --name test  --rm  debian /bin/bash
    root@a6a7c81dcfe9:/# cd share/
    root@a6a7c81dcfe9:/share# ls
    hello.txt
    root@a6a7c81dcfe9:/share# touch  hello.txt  
    root@a6a7c81dcfe9:/share# echo hello hello.txt 
    hello hello.txt
    root@a6a7c81dcfe9:/share# echo hello >> hello.txt 
    root@a6a7c81dcfe9:/share# echo hello >> hello.txt  
    root@a6a7c81dcfe9:/share# 
    root@a6a7c81dcfe9:/share# 
    root@a6a7c81dcfe9:/share# 
    root@a6a7c81dcfe9:/share# 
    root@a6a7c81dcfe9:/share# echo hello >> hello.txt  
    root@a6a7c81dcfe9:/share# 

    gdb  func (r *ReadWriter) Write(b []byte) (int, error) 

    (dlv) b fd/fd.go:110
    Breakpoint 4 set at 0x286b40 for gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt() pkg/fd/fd.go:110
    (dlv) c
    > gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt() pkg/fd/fd.go:110 (hits goroutine(102):1 total:1) (PC: 0x286b40)
    Warning: debugging optimized function
    (dlv) bt
     0  0x0000000000286b40 in gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt
        at pkg/fd/fd.go:110
     1  0x000000000069c3a4 in gvisor.dev/gvisor/pkg/secio.(*SectionWriter).Write
        at pkg/secio/secio.go:84
     2  0x0000000000159dd4 in gvisor.dev/gvisor/pkg/safemem.FromIOWriter.writeFromBlock
        at pkg/safemem/io.go:295
     3  0x0000000000159bb4 in gvisor.dev/gvisor/pkg/safemem.FromIOWriter.WriteFromBlocks
        at pkg/safemem/io.go:281
     4  0x00000000006dd784 in gvisor.dev/gvisor/pkg/sentry/fs/gofer.(*handleReadWriter).WriteFromBlocks
        at pkg/sentry/fs/gofer/handles.go:138
     5  0x00000000006de538 in gvisor.dev/gvisor/pkg/sentry/fs/gofer.(*inodeFileState).WriteFromBlocksAt
        at pkg/sentry/fs/gofer/inode.go:301
     6  0x00000000003affb0 in gvisor.dev/gvisor/pkg/sentry/fs/fsutil.(*writer).WriteFromBlocks
        at pkg/sentry/fs/fsutil/host_mappable.go:210
     7  0x00000000004033e0 in gvisor.dev/gvisor/pkg/safemem.Writer.WriteFromBlocks-fm
        at pkg/safemem/io.go:46
     8  0x00000000003db314 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).withInternalMappings
        at pkg/sentry/mm/io.go:506
     9  0x00000000003dba08 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).withVecInternalMappings
        at pkg/sentry/mm/io.go:575
    10  0x00000000003d9f14 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).CopyInTo
        at pkg/sentry/mm/io.go:309
    11  0x00000000003afe94 in gvisor.dev/gvisor/pkg/usermem.IOSequence.CopyInTo
        at pkg/usermem/usermem.go:514
    12  0x00000000003afe94 in gvisor.dev/gvisor/pkg/sentry/fs/fsutil.(*HostMappable).Write
        at pkg/sentry/fs/fsutil/host_mappable.go:197
    13  0x00000000006db464 in gvisor.dev/gvisor/pkg/sentry/fs/gofer.(*fileOperations).Write
        at pkg/sentry/fs/gofer/file.go:252
    14  0x000000000031f78c in gvisor.dev/gvisor/pkg/sentry/fs.(*File).Writev
        at pkg/sentry/fs/file.go:306
    15  0x0000000000597b28 in gvisor.dev/gvisor/pkg/sentry/syscalls/linux.writev
        at pkg/sentry/syscalls/linux/sys_write.go:262
    16  0x0000000000596470 in gvisor.dev/gvisor/pkg/sentry/syscalls/linux.Write
        at pkg/sentry/syscalls/linux/sys_write.go:72
    17  0x0000000000522ea4 in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).executeSyscall
        at pkg/sentry/kernel/task_syscall.go:104
    18  0x0000000000523c5c in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscallInvoke
        at pkg/sentry/kernel/task_syscall.go:239
    19  0x00000000005238dc in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscallEnter
        at pkg/sentry/kernel/task_syscall.go:199
    20  0x00000000005233e0 in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscall
        at pkg/sentry/kernel/task_syscall.go:174
    21  0x0000000000518e00 in gvisor.dev/gvisor/pkg/sentry/kernel.(*runApp).execute
        at pkg/sentry/kernel/task_run.go:282
    22  0x0000000000517d9c in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).run
        at pkg/sentry/kernel/task_run.go:97
    23  0x0000000000077c84 in runtime.goexit
        at src/runtime/asm_arm64.s:1136
    (dlv) c
    > gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt() pkg/fd/fd.go:110 (hits goroutine(102):2 total:2) (PC: 0x286b40)
    Warning: debugging optimized function
    (dlv) bt
     0  0x0000000000286b40 in gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt
        at pkg/fd/fd.go:110
     1  0x000000000069c3a4 in gvisor.dev/gvisor/pkg/secio.(*SectionWriter).Write
        at pkg/secio/secio.go:84
     2  0x0000000000159dd4 in gvisor.dev/gvisor/pkg/safemem.FromIOWriter.writeFromBlock
        at pkg/safemem/io.go:295
     3  0x0000000000159bb4 in gvisor.dev/gvisor/pkg/safemem.FromIOWriter.WriteFromBlocks
        at pkg/safemem/io.go:281
     4  0x00000000006dd784 in gvisor.dev/gvisor/pkg/sentry/fs/gofer.(*handleReadWriter).WriteFromBlocks
        at pkg/sentry/fs/gofer/handles.go:138
     5  0x00000000006de538 in gvisor.dev/gvisor/pkg/sentry/fs/gofer.(*inodeFileState).WriteFromBlocksAt
        at pkg/sentry/fs/gofer/inode.go:301
     6  0x00000000003affb0 in gvisor.dev/gvisor/pkg/sentry/fs/fsutil.(*writer).WriteFromBlocks
        at pkg/sentry/fs/fsutil/host_mappable.go:210
     7  0x00000000004033e0 in gvisor.dev/gvisor/pkg/safemem.Writer.WriteFromBlocks-fm
        at pkg/safemem/io.go:46
     8  0x00000000003db314 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).withInternalMappings
        at pkg/sentry/mm/io.go:506
     9  0x00000000003dba08 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).withVecInternalMappings
        at pkg/sentry/mm/io.go:575
    10  0x00000000003d9f14 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).CopyInTo
        at pkg/sentry/mm/io.go:309
    11  0x00000000003afe94 in gvisor.dev/gvisor/pkg/usermem.IOSequence.CopyInTo
        at pkg/usermem/usermem.go:514
    12  0x00000000003afe94 in gvisor.dev/gvisor/pkg/sentry/fs/fsutil.(*HostMappable).Write
        at pkg/sentry/fs/fsutil/host_mappable.go:197
    13  0x00000000006db464 in gvisor.dev/gvisor/pkg/sentry/fs/gofer.(*fileOperations).Write
        at pkg/sentry/fs/gofer/file.go:252
    14  0x000000000031f78c in gvisor.dev/gvisor/pkg/sentry/fs.(*File).Writev
        at pkg/sentry/fs/file.go:306
    15  0x0000000000597b28 in gvisor.dev/gvisor/pkg/sentry/syscalls/linux.writev
        at pkg/sentry/syscalls/linux/sys_write.go:262
    16  0x0000000000596470 in gvisor.dev/gvisor/pkg/sentry/syscalls/linux.Write
        at pkg/sentry/syscalls/linux/sys_write.go:72
    17  0x0000000000522ea4 in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).executeSyscall
        at pkg/sentry/kernel/task_syscall.go:104
    18  0x0000000000523c5c in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscallInvoke
        at pkg/sentry/kernel/task_syscall.go:239
    19  0x00000000005238dc in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscallEnter
        at pkg/sentry/kernel/task_syscall.go:199
    20  0x00000000005233e0 in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscall
        at pkg/sentry/kernel/task_syscall.go:174
    21  0x0000000000518e00 in gvisor.dev/gvisor/pkg/sentry/kernel.(*runApp).execute
        at pkg/sentry/kernel/task_run.go:282
    22  0x0000000000517d9c in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).run
        at pkg/sentry/kernel/task_run.go:97
    23  0x0000000000077c84 in runtime.goexit
        at src/runtime/asm_arm64.s:1136
    (dlv) c
    I am trying to figure out the whole code path of a write system call from application(the hello-world docker image) under KVM platform.
    
    I find that the control flow actually goes into
    
    Write -- pkg/sentry/fs/host/file.go
    
    Eventually, after a long calling chain, it reaches
    
    Write -- pkg/fd/fd.go
    (dlv) b fd/fd.go:80
    Breakpoint 2 set at 0x286970 for gvisor.dev/gvisor/pkg/fd.(*ReadWriter).Write() pkg/fd/fd.go:80
    (dlv) b fd/fd.go:110
    Breakpoint 3 set at 0x286b40 for gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt() pkg/fd/fd.go:110
    (dlv) c
    > gvisor.dev/gvisor/pkg/fd.(*ReadWriter).Write() pkg/fd/fd.go:80 (hits goroutine(102):1 total:1) (PC: 0x286970)
    Warning: debugging optimized function
    (dlv) bt
     0  0x0000000000286970 in gvisor.dev/gvisor/pkg/fd.(*ReadWriter).Write
        at pkg/fd/fd.go:80
     1  0x0000000000159dd4 in gvisor.dev/gvisor/pkg/safemem.FromIOWriter.writeFromBlock
        at pkg/safemem/io.go:295
     2  0x0000000000159bb4 in gvisor.dev/gvisor/pkg/safemem.FromIOWriter.WriteFromBlocks
        at pkg/safemem/io.go:281
     3  0x000000000015c480 in gvisor.dev/gvisor/pkg/safemem.(*FromIOWriter).WriteFromBlocks
        at <autogenerated>:1
     4  0x00000000004033e0 in gvisor.dev/gvisor/pkg/safemem.Writer.WriteFromBlocks-fm
        at pkg/safemem/io.go:46
     5  0x00000000003db314 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).withInternalMappings
        at pkg/sentry/mm/io.go:506
     6  0x00000000003dba08 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).withVecInternalMappings
        at pkg/sentry/mm/io.go:575
     7  0x00000000003d9f14 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).CopyInTo
        at pkg/sentry/mm/io.go:309
     8  0x000000000069e060 in gvisor.dev/gvisor/pkg/usermem.IOSequence.CopyInTo
        at pkg/usermem/usermem.go:514
     9  0x000000000069e060 in gvisor.dev/gvisor/pkg/sentry/fs/host.(*fileOperations).Write
        at pkg/sentry/fs/host/file.go:208
    10  0x00000000006a2c90 in gvisor.dev/gvisor/pkg/sentry/fs/host.(*TTYFileOperations).Write
        at pkg/sentry/fs/host/tty.go:113
    11  0x000000000031f78c in gvisor.dev/gvisor/pkg/sentry/fs.(*File).Writev
        at pkg/sentry/fs/file.go:306
    12  0x0000000000597b28 in gvisor.dev/gvisor/pkg/sentry/syscalls/linux.writev
        at pkg/sentry/syscalls/linux/sys_write.go:262
    13  0x0000000000596470 in gvisor.dev/gvisor/pkg/sentry/syscalls/linux.Write
        at pkg/sentry/syscalls/linux/sys_write.go:72
    14  0x0000000000522ea4 in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).executeSyscall
        at pkg/sentry/kernel/task_syscall.go:104
    15  0x0000000000523c5c in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscallInvoke
        at pkg/sentry/kernel/task_syscall.go:239
    16  0x00000000005238dc in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscallEnter
        at pkg/sentry/kernel/task_syscall.go:199
    17  0x00000000005233e0 in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscall
        at pkg/sentry/kernel/task_syscall.go:174
    18  0x0000000000518e00 in gvisor.dev/gvisor/pkg/sentry/kernel.(*runApp).execute
        at pkg/sentry/kernel/task_run.go:282
    19  0x0000000000517d9c in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).run
        at pkg/sentry/kernel/task_run.go:97
    20  0x0000000000077c84 in runtime.goexit
        at src/runtime/asm_arm64.s:1136
    (dlv) c
    > gvisor.dev/gvisor/pkg/fd.(*ReadWriter).Write() pkg/fd/fd.go:80 (hits goroutine(102):2 total:2) (PC: 0x286970)
    Warning: debugging optimized function
    (dlv) c
    > gvisor.dev/gvisor/pkg/fd.(*ReadWriter).Write() pkg/fd/fd.go:80 (hits goroutine(102):3 total:3) (PC: 0x286970)
    Warning: debugging optimized function
    (dlv) clearall
    Breakpoint 1 cleared at 0x9685b0 for gvisor.dev/gvisor/runsc/fsgofer.(*localFile).Open() runsc/fsgofer/fsgofer.go:381
    Breakpoint 2 cleared at 0x286970 for gvisor.dev/gvisor/pkg/fd.(*ReadWriter).Write() pkg/fd/fd.go:80
    Breakpoint 3 cleared at 0x286b40 for gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt() pkg/fd/fd.go:110
    (dlv) b fd/fd.go:110
    Breakpoint 4 set at 0x286b40 for gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt() pkg/fd/fd.go:110
    (dlv) c
    > gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt() pkg/fd/fd.go:110 (hits goroutine(102):1 total:1) (PC: 0x286b40)
    Warning: debugging optimized function
    (dlv) bt
     0  0x0000000000286b40 in gvisor.dev/gvisor/pkg/fd.(*ReadWriter).WriteAt
        at pkg/fd/fd.go:110
     1  0x000000000069c3a4 in gvisor.dev/gvisor/pkg/secio.(*SectionWriter).Write
        at pkg/secio/secio.go:84
     2  0x0000000000159dd4 in gvisor.dev/gvisor/pkg/safemem.FromIOWriter.writeFromBlock
        at pkg/safemem/io.go:295
     3  0x0000000000159bb4 in gvisor.dev/gvisor/pkg/safemem.FromIOWriter.WriteFromBlocks
        at pkg/safemem/io.go:281
     4  0x00000000006dd784 in gvisor.dev/gvisor/pkg/sentry/fs/gofer.(*handleReadWriter).WriteFromBlocks
        at pkg/sentry/fs/gofer/handles.go:138
     5  0x00000000006de538 in gvisor.dev/gvisor/pkg/sentry/fs/gofer.(*inodeFileState).WriteFromBlocksAt
        at pkg/sentry/fs/gofer/inode.go:301
     6  0x00000000003affb0 in gvisor.dev/gvisor/pkg/sentry/fs/fsutil.(*writer).WriteFromBlocks
        at pkg/sentry/fs/fsutil/host_mappable.go:210
     7  0x00000000004033e0 in gvisor.dev/gvisor/pkg/safemem.Writer.WriteFromBlocks-fm
        at pkg/safemem/io.go:46
     8  0x00000000003db314 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).withInternalMappings
        at pkg/sentry/mm/io.go:506
     9  0x00000000003dba08 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).withVecInternalMappings
        at pkg/sentry/mm/io.go:575
    10  0x00000000003d9f14 in gvisor.dev/gvisor/pkg/sentry/mm.(*MemoryManager).CopyInTo
        at pkg/sentry/mm/io.go:309
    11  0x00000000003afe94 in gvisor.dev/gvisor/pkg/usermem.IOSequence.CopyInTo
        at pkg/usermem/usermem.go:514
    12  0x00000000003afe94 in gvisor.dev/gvisor/pkg/sentry/fs/fsutil.(*HostMappable).Write
        at pkg/sentry/fs/fsutil/host_mappable.go:197
    13  0x00000000006db464 in gvisor.dev/gvisor/pkg/sentry/fs/gofer.(*fileOperations).Write
        at pkg/sentry/fs/gofer/file.go:252
    14  0x000000000031f78c in gvisor.dev/gvisor/pkg/sentry/fs.(*File).Writev
        at pkg/sentry/fs/file.go:306
    15  0x0000000000597b28 in gvisor.dev/gvisor/pkg/sentry/syscalls/linux.writev
        at pkg/sentry/syscalls/linux/sys_write.go:262
    16  0x0000000000596470 in gvisor.dev/gvisor/pkg/sentry/syscalls/linux.Write
        at pkg/sentry/syscalls/linux/sys_write.go:72
    17  0x0000000000522ea4 in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).executeSyscall
        at pkg/sentry/kernel/task_syscall.go:104
    18  0x0000000000523c5c in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscallInvoke
        at pkg/sentry/kernel/task_syscall.go:239
    19  0x00000000005238dc in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscallEnter
        at pkg/sentry/kernel/task_syscall.go:199
    20  0x00000000005233e0 in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).doSyscall
        at pkg/sentry/kernel/task_syscall.go:174
    21  0x0000000000518e00 in gvisor.dev/gvisor/pkg/sentry/kernel.(*runApp).execute
        at pkg/sentry/kernel/task_run.go:282
    22  0x0000000000517d9c in gvisor.dev/gvisor/pkg/sentry/kernel.(*Task).run
        at pkg/sentry/kernel/task_run.go:97
    23  0x0000000000077c84 in runtime.goexit
        at src/runtime/asm_arm64.s:1136

     SCM_RIGHTS

    The gofer mediates file system access, but may pass a FD to the sandbox via SCM_RIGHTS for regular files.

    dlv  gofer 进程

    root@cloud:~# docker run -it --runtime=runsc-kvm  -v share:/share --name test  --rm  debian /bin/bash
     
    root@a6a7c81dcfe9:/share# exit
    exit
     
    runsc/cmd/gofer.go:213:
    func runServers(ats []p9.Attacher, ioFDs []int) {
            // Run the loops and wait for all to exit.
            var wg sync.WaitGroup
            for i, ioFD := range ioFDs {
                    wg.Add(1)
                    go func(ioFD int, at p9.Attacher) {
                            socket, err := unet.NewSocket(ioFD)
                            if err != nil {
                                    Fatalf("creating server on FD %d: %v", ioFD, err)
                            }
                            s := p9.NewServer(at)
                            if err := s.Handle(socket); err != nil {
                                    Fatalf("P9 server returned error. Gofer is shutting down. FD: %d, err: %v", ioFD, err)
                            }
                            wg.Done()
                    }(ioFD, ats[i])
            }
            wg.Wait()
            log.Infof("All 9P servers exited.")
    }
    // NewServer returns a new server.
    func NewServer(attacher Attacher) *Server {
            return &Server{
                    attacher: attacher,
                    pathTree: newPathNode(),
            }
    }
    // Handle handles a single connection.
    func (s *Server) Handle(conn *unet.Socket) error {
            cs := &connState{
                    server: s,
                    fids:   make(map[FID]*fidRef),
                    tags:   make(map[Tag]chan struct{}),
                    conn:   conn,
            }
            defer cs.stop()
    
            // Serve requests from conn in the current goroutine; handleRequests() will
            // create more goroutines as needed.
            cs.handleRequests()
    
            return nil
    }

    root@cloud:~# dlv attach 944937
    Type 'help' for list of commands.
    (dlv) b p9/server.go:532
    Breakpoint 1 set at 0x2e4ea0 for gvisor.dev/gvisor/pkg/p9.(*connState).handleRequest() pkg/p9/server.go:532
    (dlv) c
    > gvisor.dev/gvisor/pkg/p9.(*connState).handleRequest() pkg/p9/server.go:532 (hits goroutine(19):1 total:1) (PC: 0x2e4ea0)
    Warning: debugging optimized function
    (dlv) bt
    0  0x00000000002e4ea0 in gvisor.dev/gvisor/pkg/p9.(*connState).handleRequest
       at pkg/p9/server.go:532
    1  0x00000000002e5478 in gvisor.dev/gvisor/pkg/p9.(*connState).handleRequests
       at pkg/p9/server.go:590
    2  0x00000000002e5788 in gvisor.dev/gvisor/pkg/p9.(*Server).Handle
       at pkg/p9/server.go:645
    3  0x00000000009900f4 in gvisor.dev/gvisor/runsc/cmd.runServers.func1
       at runsc/cmd/gofer.go:224
    4  0x0000000000077c84 in runtime.goexit
       at src/runtime/asm_arm64.s:1136
    (dlv) n
    > gvisor.dev/gvisor/pkg/p9.(*connState).handleRequest() pkg/p9/server.go:526 (PC: 0x2e4ec4)
    Warning: debugging optimized function
    (dlv) list
    > gvisor.dev/gvisor/pkg/p9.(*connState).handleRequest() pkg/p9/server.go:526 (PC: 0x2e4ec4)
    Warning: debugging optimized function
    Command failed: open pkg/p9/server.go: no such file or directory
    (dlv) n
    > gvisor.dev/gvisor/pkg/p9.(*connState).handleRequest() pkg/p9/server.go:533 (PC: 0x2e4ef4)
    Warning: debugging optimized function
    (dlv) p m
    gvisor.dev/gvisor/pkg/p9.message(*gvisor.dev/gvisor/pkg/p9.Tclunk) *{FID: 77}
    (dlv) p cs
    *gvisor.dev/gvisor/pkg/p9.connState {
            server: *gvisor.dev/gvisor/pkg/p9.Server {
                    attacher: gvisor.dev/gvisor/pkg/p9.Attacher(*gvisor.dev/gvisor/runsc/fsgofer.attachPoint) ...,
                    pathTree: *(*"gvisor.dev/gvisor/pkg/p9.pathNode")(0x400048e000),
                    renameMu: (*"gvisor.dev/gvisor/pkg/sync.RWMutex")(0x400048c0d8),},
            fidMu: gvisor.dev/gvisor/pkg/sync.Mutex {
                    m: (*"gvisor.dev/gvisor/pkg/sync.CrossGoroutineMutex")(0x4000490008),},
            fids: map[gvisor.dev/gvisor/pkg/p9.FID]*gvisor.dev/gvisor/pkg/p9.fidRef [
                    4: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048e410), 
                    64: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40002148c0), 
                    67: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40002144b0), 
                    75: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000214ff0), 
                    5: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048e550), 
                    39: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018e5f0), 
                    50: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018f270), 
                    73: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000214e10), 
                    2: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048e190), 
                    19: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048f6d0), 
                    28: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400081a7d0), 
                    37: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018e3c0), 
                    15: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048f220), 
                    38: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018e4b0), 
                    61: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000126a50), 
                    68: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40002145a0), 
                    70: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000214af0), 
                    14: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048f130), 
                    18: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048f590), 
                    42: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018e9b0), 
                    45: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018ed70), 
                    72: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000214cd0), 
                    9: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048ea50), 
                    16: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048f310), 
                    48: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018f040), 
                    49: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018f130), 
                    60: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000126960), 
                    69: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40002149b0), 
                    6: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048e690), 
                    20: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048f7c0), 
                    24: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400081a3c0), 
                    47: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018ef50), 
                    53: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000126320), 
                    77: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018f9f0), 
                    76: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018fae0), 
                    12: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048ef00), 
                    13: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048eff0), 
                    29: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400081a8c0), 
                    57: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000214140), 
                    11: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048ee10), 
                    8: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048e910), 
                    10: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048eb90), 
                    43: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018eaf0), 
                    46: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018ee60), 
                    52: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40001261e0), 
                    54: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000126460), 
                    79: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018fd10), 
                    41: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018e870), 
                    51: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018f360), 
                    56: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40001266e0), 
                    66: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018f540), 
                    22: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400081a190), 
                    36: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018e2d0), 
                    23: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400081a280), 
                    30: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400081aa00), 
                    33: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40007aa0a0), 
                    44: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018ec30), 
                    65: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400018f450), 
                    1: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048e0a0), 
                    55: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40001265a0), 
                    59: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40001267d0), 
                    63: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x40002147d0), 
                    71: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x4000214be0), 
                    3: *(*"gvisor.dev/gvisor/pkg/p9.fidRef")(0x400048e2d0), 
                    ...+14 more
            ],
            tagMu: gvisor.dev/gvisor/pkg/sync.Mutex {
                    m: (*"gvisor.dev/gvisor/pkg/sync.CrossGoroutineMutex")(0x4000490018),},
            tags: map[gvisor.dev/gvisor/pkg/p9.Tag]chan struct {} [
                    1: {
                            qcount: 0,
                            dataqsiz: 0,
                            buf: *[0]struct struct {} [],
                            elemsize: 0,
                            closed: 0,
                            elemtype: *runtime._type {size: 0, ptrdata: 0, hash: 670477339, tflag: tflagExtraStar|tflagRegularMemory (10), align: 1, fieldAlign: 1, kind: 25, equal: runtime.memequal0, gcdata: *1, str: 54665, ptrToThis: 498784},
                            sendx: 0,
                            recvx: 0,
                            recvq: waitq<struct {}> {
                                    first: *sudog<struct {}> nil,
                                    last: *sudog<struct {}> nil,},
                            sendq: waitq<struct {}> {
                                    first: *sudog<struct {}> nil,
                                    last: *sudog<struct {}> nil,},
                            lock: runtime.mutex {
                                    lockRankStruct: runtime.lockRankStruct {},
                                    key: 0,},}, 
            ],
            messageSize: 1048576,
            version: 12,
            pendingWg: sync.WaitGroup {
                    noCopy: sync.noCopy {},
                    state1: [3]uint32 [0,0,0],},
            recvMu: gvisor.dev/gvisor/pkg/sync.Mutex {
                    m: (*"gvisor.dev/gvisor/pkg/sync.CrossGoroutineMutex")(0x400049003c),},
            recvIdle: 0,
            recvShutdown: false,
            sendMu: gvisor.dev/gvisor/pkg/sync.Mutex {
                    m: (*"gvisor.dev/gvisor/pkg/sync.CrossGoroutineMutex")(0x400049004c),},
            conn: *gvisor.dev/gvisor/pkg/unet.Socket {
                    gate: (*"gvisor.dev/gvisor/pkg/gate.Gate")(0x400048c000),
                    fd: 6,
                    efd: 22,
                    race: *int32 nil,},
            channelMu: gvisor.dev/gvisor/pkg/sync.Mutex {
                    m: (*"gvisor.dev/gvisor/pkg/sync.CrossGoroutineMutex")(0x4000490060),},
            channelWg: sync.WaitGroup {
                    noCopy: sync.noCopy {},
                    state1: [3]uint32 [0,4,0],},
            channelAlloc: *gvisor.dev/gvisor/pkg/flipcall.PacketWindowAllocator {fd: 23, nextAlloc: 4210688, fileSize: 8388608},
            channels: []*gvisor.dev/gvisor/pkg/p9.channel len: 4, cap: 4, [
                    *(*"gvisor.dev/gvisor/pkg/p9.channel")(0x40004a2000),
                    *(*"gvisor.dev/gvisor/pkg/p9.channel")(0x40004a20c0),
                    *(*"gvisor.dev/gvisor/pkg/p9.channel")(0x40004a2180),
                    *(*"gvisor.dev/gvisor/pkg/p9.channel")(0x40004a2240),
            ],}
    (dlv) p tag
    5

    Command

    // Register registers a new help command.
    func (h *Help) Register(cmd subcommands.Command) {
            h.commands = append(h.commands, cmd)
    }

    "github.com/google/subcommands"

    // A Command represents a single command.
    type Command interface {
        // Name returns the name of the command.
        Name() string
        // Synopsis returns a short string (less than one line) describing the command.
        Synopsis() string
        // Usage returns a long string explaining the command and giving usage
        // information.
        Usage() string
        // SetFlags adds the flags for this command to the specified set.
        SetFlags(*flag.FlagSet)
        // Execute executes the command and returns an ExitStatus.
        Execute(ctx context.Context, f *flag.FlagSet, args ...interface{}) ExitStatus
    }
    // Register adds a subcommand to the supported subcommands in the
    // specified group. (Help output is sorted and arranged by group
    // name.)  The empty string is an acceptable group name; such
    // subcommands are explained first before named groups. It is a
    // wrapper around DefaultCommander.Register.
    func Register(cmd Command, group string) {
        DefaultCommander.Register(cmd, group)
    }
    func Execute(ctx context.Context, args ...interface{}) ExitStatus {
        return DefaultCommander.Execute(ctx, args...)
    }

     

    cli/main.go:59: help.Register(new(cmd.Syscalls))
    cli/main.go:60: subcommands.Register(help, "")
    cli/main.go:61: subcommands.Register(subcommands.FlagsCommand(), "")
    cli/main.go:65: subcommands.Register(new(cmd.Install), helperGroup)
    cli/main.go:66: subcommands.Register(new(cmd.Uninstall), helperGroup)
    cli/main.go:68: // Register user-facing runsc commands.
    cli/main.go:69: subcommands.Register(new(cmd.Checkpoint), "")
    cli/main.go:70: subcommands.Register(new(cmd.Create), "")
    cli/main.go:71: subcommands.Register(new(cmd.Delete), "")
    cli/main.go:72: subcommands.Register(new(cmd.Do), "")
    cli/main.go:73: subcommands.Register(new(cmd.Events), "")
    cli/main.go:74: subcommands.Register(new(cmd.Exec), "")
    cli/main.go:75: subcommands.Register(new(cmd.Gofer), "")
    cli/main.go:76: subcommands.Register(new(cmd.Kill), "")
    cli/main.go:77: subcommands.Register(new(cmd.List), "")
    cli/main.go:78: subcommands.Register(new(cmd.Pause), "")
    cli/main.go:79: subcommands.Register(new(cmd.PS), "")
    cli/main.go:80: subcommands.Register(new(cmd.Restore), "")
    cli/main.go:81: subcommands.Register(new(cmd.Resume), "")
    cli/main.go:82: subcommands.Register(new(cmd.Run), "")
    cli/main.go:83: subcommands.Register(new(cmd.Spec), "")
    cli/main.go:84: subcommands.Register(new(cmd.State), "")
    cli/main.go:85: subcommands.Register(new(cmd.Start), "")
    cli/main.go:86: subcommands.Register(new(cmd.Symbolize), "")
    cli/main.go:87: subcommands.Register(new(cmd.Wait), "")
    cli/main.go:89: // Register internal commands with the internal group name. This causes
    cli/main.go:93: subcommands.Register(new(cmd.Boot), internalGroup)
    cli/main.go:94: subcommands.Register(new(cmd.Debug), internalGroup)
    cli/main.go:95: subcommands.Register(new(cmd.Gofer), internalGroup)
    cli/main.go:96: subcommands.Register(new(cmd.Statefile), internalGroup)
    cli/main.go:98: config.RegisterFlags()
    var ws syscall.WaitStatus
            subcmdCode := subcommands.Execute(context.Background(), conf, &ws)
            if subcmdCode == subcommands.ExitSuccess {
                    log.Infof("Exiting with status: %v", ws)
                    if ws.Signaled() {
                            // No good way to return it, emulate what the shell does. Maybe raise
                            // signal to self?
                            os.Exit(128 + int(ws.Signal()))
                    }
                    os.Exit(ws.ExitStatus())
            }
  • 相关阅读:
    android基本架构
    c#编辑框只接受数字
    listbox数据源绑定问题
    QQ在线客服代码
    用VB生成DLL封装ASP代码例子
    C#,关于DataGridView的一些方法
    转:ASP.NET中引用dll“找不到指定模块"的完美解决办法
    编译asp.net文件为dll文件
    好看的表格样式
    网站IIS日志解读
  • 原文地址:https://www.cnblogs.com/dream397/p/14297135.html
Copyright © 2020-2023  润新知