• prepareRootfs +createDevices


    // prepareRootfs sets up the devices, mount points, and filesystems for use
    // inside a new mount namespace. It doesn't set anything as ro. You must call
    // finalizeRootfs after this function to finish setting up the rootfs.
    func prepareRootfs(pipe io.ReadWriter, iConfig *initConfig) (err error) {
            config := iConfig.Config
            if err := prepareRoot(config); err != nil {
                    return newSystemErrorWithCause(err, "preparing rootfs")
            }
    
            hasCgroupns := config.Namespaces.Contains(configs.NEWCGROUP)
            setupDev := needsSetupDev(config)
            for _, m := range config.Mounts {
                    for _, precmd := range m.PremountCmds {
                            if err := mountCmd(precmd); err != nil {
                                    return newSystemErrorWithCause(err, "running premount command")
                            }
                    }
                    if err := mountToRootfs(m, config.Rootfs, config.MountLabel, hasCgroupns); err != nil {
                            return newSystemErrorWithCausef(err, "mounting %q to rootfs %q at %q", m.Source, config.Rootfs, m.Destination)
                    }
    
                    for _, postcmd := range m.PostmountCmds {
                            if err := mountCmd(postcmd); err != nil {
                                    return newSystemErrorWithCause(err, "running postmount command")
                            }
                    }
            }
    
            if setupDev {
                    if err := createDevices(config); err != nil {
                            return newSystemErrorWithCause(err, "creating device nodes")
                    }
                    if err := setupPtmx(config); err != nil {
                            return newSystemErrorWithCause(err, "setting up ptmx")
                    }
                    if err := setupDevSymlinks(config.Rootfs); err != nil {
                            return newSystemErrorWithCause(err, "setting up /dev symlinks")
                    }
            }
    // Create the device nodes in the container.
    func createDevices(config *configs.Config) error {
            useBindMount := system.RunningInUserNS() || config.Namespaces.Contains(configs.NEWUSER)
            oldMask := unix.Umask(0000)
            for _, node := range config.Devices {
                    // containers running in a user namespace are not allowed to mknod
                    // devices so we can just bind mount it from the host.
                    if err := createDeviceNode(config.Rootfs, node, useBindMount); err != nil {
                            unix.Umask(oldMask)
                            return err
                    }
            }
            unix.Umask(oldMask)
            return nil
    }
    // Creates the device node in the rootfs of the container.
    func createDeviceNode(rootfs string, node *configs.Device, bind bool) error {
            dest := filepath.Join(rootfs, node.Path)
            if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil {
                    return err
            }
    
            if bind {
                    return bindMountDeviceNode(dest, node)
            }
            if err := mknodDevice(dest, node); err != nil {
                    if os.IsExist(err) {
                            return nil
                    } else if os.IsPermission(err) {
                            return bindMountDeviceNode(dest, node)
                    }
                    return err
            }
            return nil
    }
    
    func mknodDevice(dest string, node *configs.Device) error {
            fileMode := node.FileMode
            switch node.Type {
            case 'c', 'u':
                    fileMode |= unix.S_IFCHR
            case 'b':
                    fileMode |= unix.S_IFBLK
            case 'p':
                    fileMode |= unix.S_IFIFO
            default:
                    return fmt.Errorf("%c is not a valid device type for device %s", node.Type, node.Path)
            }
            if err := unix.Mknod(dest, uint32(fileMode), node.Mkdev()); err != nil {
                    return err
            }
            return unix.Chown(dest, int(node.Uid), int(node.Gid))
    }
    - switch {
    - case mode&unix.S_IFBLK == unix.S_IFBLK:
    + switch mode & unix.S_IFMT {
    + case unix.S_IFBLK:
        devType = configs.BlockDevice
    - case mode&unix.S_IFCHR == unix.S_IFCHR:
    + case unix.S_IFCHR:
        devType = configs.CharDevice
    - case mode&unix.S_IFIFO == unix.S_IFIFO:
    + case unix.S_IFIFO:
        devType = configs.FifoDevice
    default:
        return nil, ErrNotADevice
    // include/uapi/linux/stat.h
    #define S_ISLNK(m)  (((m) & S_IFMT) == S_IFLNK)
    #define S_ISREG(m)  (((m) & S_IFMT) == S_IFREG)
    #define S_ISDIR(m)  (((m) & S_IFMT) == S_IFDIR)
    #define S_ISCHR(m)  (((m) & S_IFMT) == S_IFCHR)
    #define S_ISBLK(m)  (((m) & S_IFMT) == S_IFBLK)
    #define S_ISFIFO(m)  (((m) & S_IFMT) == S_IFIFO)
    #define S_ISSOCK(m)  (((m) & S_IFMT) == S_IFSOCK)
    'm running a GUI app inside Docker on Raspberry Pi. I need to use keyboard in that app.
    
    So far I got to the point, where I run the container as privileged and I mount /run/udev to it which enables detection of the keyboard even when it's disconnected and reconnected again.
    
    docker run -d --privileged -v /run/udev:/run/udev:ro <image>
    Because it's privileged, if I exec into the container, I can see the keyboard devices:
    
    ls /dev/input
    by-id  by-path  event0  event1  event2  event3  event4  event5  mice  mouse0  mouse1
    However, if I first start the container with no keyboard connected and then connect the keyboard, these devices won't show up in the container and I can't use the keyboard:
    
    ls /dev/input
    event0  mice    mouse0
  • 相关阅读:
    记录下IE7下的input标签bug
    CYQ.Data 轻量数据访问层(一) 概述
    网站安装打包 软件环境检测与安装[二] 上
    记录下关于调用RAR解压缩的问题
    CYQ.Data 轻量数据访问层(六) 构造数据表
    记绕过路由封杀问题
    MapXtreme 2005 学习心得 一些问题(八)
    网站安装打包 修改app.config[六]
    关于控件导出Excel格式问题的新解决方案
    CYQ.Data 轻量数据访问层(二) 构造数据单元(上)
  • 原文地址:https://www.cnblogs.com/dream397/p/14000035.html
Copyright © 2020-2023  润新知