neovim
安装 参考 https://github.com/neovim/neovim/blob/master/INSTALL.md 配置文件 nvim 的配置文件目录在 ~/.config/nvim 下,默认读取该目录下的init.lua 文件。
安装 参考 https://github.com/neovim/neovim/blob/master/INSTALL.md 配置文件 nvim 的配置文件目录在 ~/.config/nvim 下,默认读取该目录下的init.lua 文件。
Problem xv6 中的 fork() 系统调用会将父进程的所有用户空间内存复制到子进程中,如果父进程很大,复制过程可能会花费很长时间。 更糟糕的是,这项工作通常是多余的:子进程 fork() 后面通常跟着 exec(),会丢弃复制的内存,通常不会使用其中的大部分。 另一方面,如果父进程和子进程都使用复制的页面,并且其中一个或两个都对其进行了写入,则复制确实是必要的。 Analysis 实现 copy-on-write (COW) fork() 的目标是推迟 allocating 和 copying 物理内存页面,直到实际需要复制为止(如果有的话)。 COW fork() 只会为子进程创建一个页表,其中用户内存的 PTE 指向父进程的物理页面。COW fork() 将父进程和子进程中的所有用户 PTE 标记为只读。当任何一个进程尝试写入其中一个 COW 页面时,CPU 都会强制触发 page fault。内核 page fault handler 会检测到这种情况,为发生错误的进程分配 a page of physical memory,将 original page 复制到 new page 中,并修改发生错误的进程中相关的 PTE 指向 new page,此时 PTE 标记为可写。当 page fault handler 返回时,用户进程将能够写入 page。 这边父进程和子进程都需要将 pte 标记为只读,这样在写任意一个进程发生 page fault 时,内核都会分配一个新页,并复制原始页的内容到新页,做到进程隔离。 如果只标记子进程的 pte 为只读,那么如果父进程先写入,则不会触发 page fault,从而不会分配新页,而在原来的页上修改。而此时子进程的 virtual address 还指向原来的页,内容也被修改了。...
4.1 Video Capture Interface 4.13 Sub-device Interface 4.13.1 Controls 大部分 V4L2 controls 都由 sub-device hardware 实现,drivers 通常会把所有 controls 合并起来,通过 video device nodes 暴露给 userspace。 复杂的设备有时会在不同的硬件中实现相同的 control,例如对比度调整、白平衡。这时可以通过 sub-device 的 node 将 control 暴露出去,区别是通过不同的 sub-device 来实现某个功能的调整。 4.13.3 Pad-level Formats 图像的 format 通常使用 format 和 selection ioctl 在 video capture/output devices 之间协商。driver 负责将 video pipeline 中每个 block 都设置好该配置。 然而对于一些复杂的设备,相同的 pipeline output size 可以通过不同的硬件配置达到。比如图像缩放可以通过 sensor 或者 isp 实现。 sensor 实现缩放一般质量更低,但可以实现更高的帧率。根据应用场景不同 (图像质量 or 速度),pipeline 必须要下不同的配置,app 必须对 pipeline 中的每一个点去下配置。...
Common API Elements 1.1 Opening and Closing Devices 1.1.1 Controlling a hardware peripheral via V4L2 需要使用 media controller 的设备称为以 MC-centric 设备。通过 V4L2 device node 完全控制的设备 称为 video-node-centric 设备。 可以通过 ioctl VIDIOC_QUERYCAP 检查 device_caps field, 如果有 V4L2_CAP_IO_MC, 则是 MC-centric 的。 MC-centric 设备需要通过 media controller api 来 configure pipeline。 video-node-centric 设备也可能提供 media controller 和 sub-device interface. 但在这种情况下,media controller 和 sub-device 只是可读的,用来提供信息,所有的 configuration 都由 video node 来下。 1.1.2 V4L2 Device Node Naming V4L2 的 device node 主设备号为 81,次设备号是动态分配的,除非设定 CONFIG_VIDEO_FIXED_MINOR_RANGES 来指定范围。...
struct v4l2_pix_format 和 v4l2_pix_format_mplane 定义了 image in memory 的 format 和 layout。 2.1 Single-planar format structure struct v4l2_pix_format { __u32 width; __u32 height; __u32 pixelformat; __u32 field; /* enum v4l2_field */ __u32 bytesperline; /* for padding, zero if unused */ __u32 sizeimage; __u32 colorspace; /* enum v4l2_colorspace */ __u32 priv; /* private data, depends on pixelformat */ __u32 flags; /* format flags (V4L2_PIX_FMT_FLAG_*) */ union { /* enum v4l2_ycbcr_encoding */ __u32 ycbcr_enc; /* enum v4l2_hsv_encoding */ __u32 hsv_enc; }; __u32 quantization; /* enum v4l2_quantization */ __u32 xfer_func; /* enum v4l2_xfer_func */ }; 2....
V4L2 API 定义了几种不同的方法来读取或写入设备。 3.1 Read/Write driver capabilities 需要置起 V4L2_CAP_READWRITE。 不会传递 frame counter 和 timestamp, 最简单的 I/O 方法。 3.2 Streaming I/O (Memory Mapping) 3.3 Streaming I/O (User Pointers) 3.4 Streaming I/O (DMA buffer importing)
graph TD A[用户进程运行] --> B{时间片到期/系统调用/中断} B --> C[进入内核态 usertrap] C --> D[保存用户寄存器到trapframe] D --> E{需要切换进程?} E -->|是| F[调用yield函数] E -->|否| G[处理完毕返回用户态] F --> H[获取进程锁 p->lock] H --> I[设置进程状态为RUNNABLE] I --> J[调用sched函数] J --> K[检查锁状态和中断状态] K --> L[保存中断状态] L --> M[调用swtch函数进行上下文切换] M --> N[保存当前进程的callee-saved寄存器到p->context] N --> O[恢复调度器的callee-saved寄存器从cpu->context] O --> P[返回到scheduler函数] P --> Q[scheduler循环查找RUNNABLE进程] Q --> R{找到可运行进程?} R -->|否| Q R -->|是| S[设置进程状态为RUNNING] S --> T[再次调用swtch函数] T --> U[保存调度器寄存器到cpu->context] U --> V[恢复新进程寄存器从p->context] V --> W[返回到新进程的内核栈] W --> X[释放进程锁] X --> Y[恢复中断状态] Y --> Z[返回到usertrapret] Z --> AA[恢复用户寄存器从trapframe] AA --> BB[切换到用户页表] BB --> CC[返回用户态继续执行] G --> AA style A fill:#e1f5fe style CC fill:#e8f5e8 style M fill:#fff3e0 style T fill:#fff3e0 style P fill:#f3e5f5 style Q fill:#f3e5f5 重要的数据结构: // 保存内核上下文切换时的寄存器 struct context { uint64 ra; // 返回地址 uint64 sp; // 栈指针 // callee-saved 寄存器 s0-s11 uint64 s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11; }; // 每个进程的状态 struct proc { struct spinlock lock; enum procstate state; // 进程状态 struct context context; // 上下文切换时保存的寄存器 struct trapframe *trapframe; // 用户态寄存器保存区 // ....
https://docs.kernel.org/userspace-api/media/index.html Video for Linux API 7. Function reference 7.3 ioctl VIDIOC_CREATE_BUFS Create buffers for Memory Mapped or User Pointer or DMA Buffer I/O. 可以用作 ioctl VIDIOC_REQBUFS 的替代。 struct v4l2_create_buffers { __u32 index; __u32 count; __u32 memory; struct v4l2_format format; __u32 capabilities; __u32 flags; __u32 max_num_buffers; __u32 reserved[5]; }; app: count: 要创建的 buffer 的数量。 memory: 要创建的 buffer 的内存类型。enum v4l2_memory. format: 要创建的 buffer 的格式。通常需要先通过 VIDIOC_TRY_FMT 或者 VIDIOC_G_FMT 获取。 flags: 要创建的 buffer 的 flags....
5.1 Media Controller 5.1.1 Abstract media device model entity 用来抽象一个 media hardware block, 可以表示一个物理硬件设备 (CMOS sensor), 也可以表示一个逻辑硬件设备 (isp pipeline) 等。 pad 用来在 entity 之间传输数据,数据从 source pad 流向 sink pad. link 是两个 pad 之间 point-to-point 的连接。 5.1.2 Media device struct media_device 注册 media_device 需要调用:media_device_init(), media_device_register(). 注销:media_device_unregister(), media_device_cleanup(). struct media_device { struct device *dev; struct media_devnode *devnode; char model[32]; char driver_name[32]; char serial[40]; char bus_info[32]; u32 hw_revision; u64 topology_version; u32 id; struct ida entity_internal_idx; int entity_internal_idx_max; struct list_head entities; struct list_head interfaces; struct list_head pads; struct list_head links; struct list_head entity_notify; struct mutex graph_mutex; struct media_graph pm_count_walk; const struct media_device_ops *ops; struct mutex req_queue_mutex; atomic_t request_id; }; dev: 底层的 device parent....
Overview V4L2 memory-to-memory 设备可以在内存中 compress, decompress、transform 或以其他方式将视频数据从一种格式转换为另一种格式。此类 memory-to-memory 设备会设置 video device device_caps 的 V4L2_CAP_VIDEO_M2M 或 V4L2_CAP_VIDEO_M2M_MPLANE flag。内存到内存设备的示例包括 codecs、scalers、deinterlacers 或 format converters(例如,从 YUV 转换为 RGB)。 memory-to-memory video device node 的行为与普通 video device node 类似,但它同时支持 output(将 frame 从内存发送到硬件)和 capture(将处理后的 frame 从硬件接收到内存)stream I/O。 memory-to-memory 设备是一种共享资源,可以多次 open video device node,每个 application 通过他们的 file handler 设置属于自己的属性,并且每个 application 都可以独立地使用它。 driver 会 arbitrate 硬件的访问,在其他 file handler 获得访问权限时对硬件进行重新编程。这与 normal video device node 的行为不同,在 normal device node 中,属性是全局的。 normal v4l2 driver:...