《Linux Device Drivers》第六章 高级字符驱动程序操作——note

Linux下的驱动开发一 模块许可证声明(MODULE_LICENSE):指定模块的许可证类型,通常为"GPL"(GNU General Public License),表明模块可以与内核兼容,否则内核可能拒绝加载非GPL的模块。模块初始化函数(module_init):这是内核加载模块时调用的函数,用来初始化模块,注册设备驱动或其他功能。通常通过module_init()宏指定初始化函数。模块退出函数(module_exit):这是在卸载模块时调用的函数,用于清理资源、注销设备驱动等。 阅读详情
  • ioctl
    • 支持的操作,例如
      • 简单数据传输
      • 控制动作,例如用户空间发起弹出介质动作
      • 反馈硬件的状态,例如报告错误信息
      • 参数配置,例如改变波特率
      • 执行自破坏
    • 用户空间的ioctl方法原型:int ioctl(int fd, unsigned long cmd, …);每个ioctl命令就是一个独立的系统调用,而且是非公开的
    • 驱动程序的ioctl方法原型:int (*ioctl) (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
    • 选择ioctl命令
      • 为方便程序员创建唯一的ioctl命令号,每一个命令号被分为多个位字段
      • Linux内核的约定方法为驱动程序选择ioctl编号
        • include/asm/ioctl.h
          • 定义了要使用的位字段
            • 类型(幻数)
            • 序数
            • 传送方向
            • 参数大小
        • Documentation/ioctl-number.txt
          • 罗列了内核所使用的幻数
      • <linux/ioctl.h>
        • type
          • 幻数,这个字段有8位宽(_IOC_TYPEBITS)
        • number
          • 序数,8位宽(_IOC_NRBITS)
        • direction
          • _IOC_NONE(没有数据传输)
          • _IOC_READ
          • _IOC_WRITE
          • _IOC_READ | _IOC_WRITE(双向传输数据)
        • size
          • 所涉及的用户数据大小
          • 通常是13位或14位
          • _IOC_SIZEBITS
      • <asm/ioctl.h>
        • _IO(type, nr)
          • 用于构造无参数的命令编号
        • _IOR(type, nr, datatype)
          • 用于构造从驱动程序中读取数据的命令编号
        • _IOW(type, nr, datatype)
          • 用于构造写入数据的命令
        • _IOWR(type, nr, datatype)
          • 用于双向传输
        • _IOC_DIR(nr)
        • _IOC_TYPE(nr);
        • _IOC_NR(nr)
        • _IOC_SIZE(nr);
    • 返回值
      • ioctl的实现通常就是一个基于命令号的switch语句
      • 不能匹配任何合法的操作?
        • 有些内核函数会返回-EINVAL
        • POSIX标准规定,如果使用了不合适的ioctl命令参数,应该返回-ENOTTY
    • 预定义命令
      • 预定义命令分为三组
        • 可用于任何文件(普通、设备、FIFO和套接字)的命令
        • 只用于普通文件的命令
        • 特定于文件系统类型的命令
      • 设备驱动程序开发人员只对第一组感兴趣,它们的幻数都是“T”
      • FIOCLEX
        • 设置执行时关闭标志
      • FIONCLEX
        • 清除执行时关闭标志
      • FIOASYNC
        • 设置或复位文件异步通知
        • 这两个动作都可以通过fcntl完成,实际上没有人会使用FIOASYNC
      • FIOQSIZE
        • 返回文件或目录的大小
      • FIONBIO
        • 文件ioctl非阻塞型I/O
    • 使用ioctl参数
      • <asm/uaccess.h>
        • int access_ok(int type, const void *addr, unsigned long size);
        • type
          • VERIFY_READ
          • VERIFY_WRITE
        • addr
          • 用户地址空间
        • size
          • 字节数
        • 返回一个布尔值:1表示成功,0表示失败
        • 如果返回失败,驱动程序通常要返回-EFAULT给调用者
        • put_user(datum, ptr);
        • __put_user(datum, ptr);
        • get_user(local, ptr);
        • __get_user(local, ptr);
    • 权能与受限操作
      • 基于权能(capability)的系统把特权操作划分为独立的组
      • capget
      • capset
      • <linux/capability.h>
        • CAP_DAC_OVERRIDE
          • 超过文件或目录的访问限制的能力
        • CAP_NET_ADMIN
          • 执行网络管理任何的能力
        • CAP_SYS_MODULE
          • 载入或卸除内核模块的能力
        • CAP_SYS_RAWIO
          • 执行“裸”I/O操作的能力
        • CAP_SYS_ADMIN
          • 截获的能力
        • CAP_SYS_TTY_CONFIG
          • 执行tty配置任务的能力
      • <sys/sched.h>
        • int capable(int capability);

  • 阻塞型I/O
    • 休眠的简单介绍
      • 当一个进程被置入休眠时,它会被标记为一种特殊状态并从调度器的运行队列中移走
      • 永远不要在原子上下文中进入休眠
      • 如果代码在拥有信号量时休眠,任何其他等待该信号量的线程也会休眠,因此任何拥有信号量而休眠的代码必须很短,并且还要确保拥有信号量并不会阻塞唤醒我们自己的那个进程
      • 当我们被唤醒时,我们永远无法知道休眠了多长时间,或者休眠期间都发生了些什么事情
      • 在Linux中,一个等待队列通过一个“等待队列头(wait queue head)”来管理
        • <linux/wait.h>
        • wait_queue_head_t
        • DECLARE_WAIT_QUEUE_HEAD(name);
        • wait_queue_head_t my_queue;
        • init_waitqueue_head(&my_queue);
    • 简单休眠
      • wait_event(queue, condition);
      • wait_event_interruptible(queue, condition);
      • wait_event_timeout(queue, condition, timeout);
      • wait_event_interruptible_timeout(queue, condition, timeout);
      • void wake_up(wait_queue_head_t *queue);
      • void wake_up_interruptible(wait_queue_head_t *queue);
    • 阻塞和非阻塞型操作
      • 显式的非阻塞I/O由filp->f_flags中的O_NONBLOCK标志决定
      • <linux/fcntl.h>
        • 自动包含在<linux/fs.h>中
      • 在执行阻塞型操作的情况下,应该实现下列动作以保持和标准语义一致
        • 如果一个进程调用了read但是还没有数据可读,此进程必须阻塞
        • 如果一个进程调用了write但缓冲区没有空间,此进程必须阻塞,而且必须休眠在与读取进程不同的等待队列上
    • 高级休眠
      • 进程如何休眠
        • 将进程置于休眠的第一个步骤通常是分配并初始化一个wait_queue_t结构,然后将其加入到对应的等待队列
        • 第二个步骤是设置进程的状态,将其标记为休眠
          • <linux/sched.h>
          • TASK_RUNNING
          • TASK_INTERRUPTIBLE
          • TASK_UNINTERRUPUTIBLE
          • void set_current_state(int new_state);
        • 放弃处理器是最后的步骤,但在此之前还要做另外一件事情:我们必须首先检查休眠等待的条件
          • if (!condition) schedule();
      • 手工休眠
        • <linux/sched.h>
        • DEFINE_WAIT(my_wait);
        • wait_queue_t my_wait;
        • init_wait(&my_wait);
        • void prepare_to_wait(wait_queue_head_t *queue, wait_queue_t *wait, int state);
          • state是进程的新状态,应该是TASK_INTERRUPTIBLE或TASK_UNINTERRUPTIBLE
        • schedule();
        • void finish_wait(wait_queue_head_t *queue, wait_queue_t *wait);
      • 独占等待
        • 当某个进程在等待队列上调用wake_up时,所有等待在该队列上的进程都被置为可运行状态
        • 只会有一个被唤醒的进程可以获得期望的资源,而其他被唤醒的进程只会再次休眠
        • 一个独占等待的行为和通常的休眠类似,但有如下两个重要的不同
          • 等待队列入口设置了WQ_FLAG_EXCLUSIVE标志时,则会被添加到等待队列的尾部
          • 在某个等待队列上调用wake_up时,它会在唤醒第一个具有WQ_FLAG_EXCLUSIVE标志的进程之后停止唤醒其他进程
        • 如果满足下面两个条件,在驱动程序中利用独占等待是值得考虑的
          • 对某个资源存在严重竞争,并且唤醒单个进程就能完整消耗该资源
        • void prepare_to_wait_exclusive(wait_queue_head_t *queue, wait_queue_t *wait, int state);
      • 唤醒的相关细节
        • <linux/wait.h>
        • wake_up(wait_queue_head_t *queue);
          • 唤醒队列上所有非独占等待的进程,以及单个独占等待者
        • wake_up_interruptible(wait_queue_head_t *queue);
          • 会跳过不可中断休眠的那些进程
        • wake_up_nr(wait_queue_head_t *queue, int nr);
          • 只会唤醒nr个独占等待进程
        • wake_up_interruptible_nr(wait_queue_head_t *queue, int nr);
          • 只会唤醒nr个独占等待进程
        • wake_up_all(wait_queue_head_t *queue);
        • wake_up_interruptible_all(wait_queue_head_t *queue);
        • wake_up_interruptible_sync(wait_queue_head_t *queue);
      • 旧的历史:sleep_on
        • void sleep_on(wait_queue_head_t *queue);
        • void interruptible_sleep_on(wait_queue_head_t *queue);
        • 永远不要使用它们
  • poll和select
    • poll、select和epoll系统调用
    • poll、select和epoll的功能本质上是一样的:都允许进程决定是否可以对一个或多个打开的文件做非阻塞的读取或写入
    • select在BSD Unix中引入
    • poll由System V引入
    • unsigned int (*poll) (struct file *filp, poll_table *wait);
    • poll_table结构,用于在内核中实现poll、select及epool系统调用
    • <linux/poll.h>
    • void poll_wait(struct file *, wait_queue_head_t *, poll_table *);
    • poll方法执行的第二项任务是返回描述哪个操作可以立即执行的位掩码
      • <linux/poll.h>
      • POLLIN
        • 如果设备可以无阻塞地读取,就设置该位
      • POLLRDNORM
        • 如果“通常”的数据已经就绪,可以读取,就设置该位
        • 一个可读设备返回(POLLIN|POLLRDNORM)
      • POLLRDBAND
        • 这一位指示可以从设备读取out-of-band的数据
      • POLLPRI
        • 可以无阻塞地读取高优先级的数据
      • POLLHUP
        • 当读取设备的进程到达文件尾时,驱动程序必须设置POLLHUP位
      • POLLERR
        • 设备发生了错误
      • POLLOUT
        • 如果设备可以无阻塞地写入,就在返回值中设置该位
      • POLLWRNORM
        • 该位和POLLOUT的意义一样,有时其实就是同一个数字
        • 一个可写的设备将返回(POLLOUT|POLLWRNORM)
      • POLLWRBAND
        • 与POLLRDBAND类似,这一位表示具有非零优先级的数据可以被写入设备
      • POLLRDBAND和POLLWRBAND只在与套接字相关的文件描述符中才是有意义的,设备驱动程序通常用不到这两个标志
    • 与read和write的交互
      • 从设备读取数据
        • 如果输入缓冲区有数据,那么即使就绪的数据比程序所请求的少,并且驱动程序保证剩下的数据马上就能到达,read调用仍然应该以难以察觉的延迟立即返回
        • 如果缓冲区中没有数据,那么默认情况下read必须阻塞等待,直到至少有一个字节到达;如果设置了O_NONBLOCK标志,read应立即返回,返回值是-EAGAIN。poll必须报告设备不可读
        • 如果已经到达文件尾,read应该立即返回0,此时poll应该报告POLLHUP
      • 向设备写数据
        • 如果输出缓冲区中有空间,则write应该无延迟地立即返回,在这种情况下,poll报告设备可写
        • 如果输出缓冲区已满,那么默认情况下write被阻塞直到有空间释放;如果设置了O_NONBLOCK标志,write应立即返回,返回值是-EAGAIN。poll必须报告设备不可写
        • 永远不要让write调用在返回前等待数据的传输结束
      • 刷新待处理输出
        • int (*fsync) (struct file *file, struct dentry *dentry, int datasync);
        • 如果应用程序需要确保数据已经被传送到设备上,就必须fsync方法
        • datasync用于区分fsync和fdatasync这两个系统调用
    • 底层的数据结构
      • poll_table结构是构成实际数据结构的一个简单封装,包含poll_table_entry结构的内存页链表
      • 每个poll_table_entry结构包括一个指向被打开设备的struct file类型的指针、一个wait_queue_head_t指针以及一个关联的等待队列入口
      • 如果轮询(poll)时没有一个驱动程序可以进行非阻塞I/O,这个poll调用者就进入休眠,直到休眠在其上的某个(或多个)等待队列唤醒它为止
      • poll实现中的珍上有趣之处是,驱动程序的poll方法在被调用者时为plol_table参数传递NULL指针。
      • 在poll调用结束时,poll_table结构被重新分配,所有的先前添加到poll表中的等待队列入口都会从这个表以及等待队列中移除
  • 异步通知
    • 为了启用文件袋异步通知机制,用户程序必须执行两个步骤
      • 首先,它们指定一个进程作为文件的属主,当进程使用fcntl系统调用执行F_SETOWN命令时,属主进程的进程ID号就被保存在filp->f_owner中
      • 然后,用户程序必须在设备中设备FASYNC标志,通过fcntl的F_SETFL命令完成的
    • 例子
      • struct sigaction action;
      • memset(&action, 0, sizeof(action));
      • action.sa_handler = sighandler;
      • action.sa_flags = 0;
      • sigaction(SIGIO, &action, NULL);
      • fcntl(STDIN_FILENO, F_SETOWN, getpid());
      • oflags = fcntl(STDIN_FILENO, F_GETFL);
      • fcntl(STDIN_FILENO, F_SETFL, oflags | FASYNC);
    • 从驱动程序的角度考虑
      • 从内核角度来看的详细操作过程
        • F_SETOWN被调用时对filp->f_owner赋值,此外什么也不做
        • 在执行F_SETFL启用FASYNC时,调用驱动程序的fasync方法,只要filp->f_flags中的FASYNC标志发生了变化,就会调用该方法,以便把这个变化通知驱动程序,使其能正确响应
        • 当数据到达时,所有注册为异步通知的进程都会被发送一个SIGIO信号
      • <linux/fs.h>
      • struct fasync_struct
      • int fasync_helper(int fd, struct file *filp, int mode, struct fasync_struct **fa);
      • void kill_fasync(struct fasync_struct **fa, int sig, int band);
        • sig通常是SIGIO
        • band通常是POLL_IN,等价于POLLIN|POLLRDNORM
      • 某些设备也针对设备可写入而实现了异步通知,在这种情况下,kill_fasync必须以POLL_OUT为模式调用
      • 当文件关闭时必须的调用fasync方法
  • 定位设备
    • llseek实现
      • 如果设备操作未定义llseek方法,内核默认通过修改filp->f_pos而执行定位
      • 如果定位操作对应于设备的一个物理操作,可能就需要提供自己的llseek方法
      • 如果定位设备是没有意义的,应该在open方法中调用nonseekable_open,通知内核设备不支持llseek
      • int nonseekable_open(struct inode *inode, struct file *filp);
      • 还应该将file_operations结构中的llseek方法设置为特殊的辅助函数no_llseek
  • 设备文件的访问控制
    • 独享设备
      • 最生硬的访问控制方法是一次只允许一个进程打开设备
    • 限制每次只由一个用户访问
      • 需要两个数据项
        • 一个打开计数
        • 设备属主的UID
      • current->uid
      • current->euid
    • 替代EBUSY的阻塞型open
      • 当设备不能访问时返回一个错误,通常这是最合理的方式,但有些情况下可能需要让进程等待设备
    • 在打开时复制设备
      • 另一个实现访问控制的方法是,在进程打开设备时创建设备的不同私有副本
一文看懂Linux内核Device和Driver匹配原理 Linux内核Device和Driver匹配过程详解 阅读详情

相关推荐

《Linux Device Driver》——Linux设备模型

Linux设备模型的目的是:为内核建立起一个统一的设备模型,从而有一个对系统结构的一般性抽象描述。 现在内核使用设备模型支持多种不同的任务: 设备模型 描述 电源管理和系统关机 这些需要对系统结构的理解,设备模型使OS能以正确顺序遍历系统硬件。 与用户空间的通讯 sysfs 虚拟文件系统的实现与设备模型的紧密相关, 并向外界展示它所表述的结构。向用户空间提供系统信息、改变操作参数的接口正越来越多地通过 sysfs , 也就是设备模型来完成。 热插拔设备 外围设备可根据用户的需要安装与

sunr_的博客 854

Linux Device Drivers(设备驱动程序)_转自老刘的blog

Chapter 8Device Drivers(设备驱动程序) 操作系统的目标之一是向用户掩盖系统硬件设备的特殊性。例如,虚拟文件系统呈现给用户一个统一的文件系统视图,而和底层的物理设备无关。本章描述Linux内核是如何管理系统中的物理设备的。CPU不是系统中唯一的智能设备,每一个物理设备都由它自己的硬件控制器。键盘、鼠标和串行口由SuperIO芯片控制,IDE磁盘由IDE控制器控制,SCSI磁盘

橙色温暖的专栏 3625

linux内核部件分析(九)——设备驱动模型之device-driver

前面我们分析了device、driver、bus三种类型,主要是三者的注册与注销,在sysfs中的目录与属性文件创建等内容。本节就来详细分析下,在设备注册到总线上时,总线是如何为其寻找对应的驱动的;在驱动注册到总线上时,总线又是如何为其寻找对应的设备的。     本节的实现代码

qb_2008的专栏 5938

Linux driver(一)

Linux driver

xy12138201611的博客 1399

《Linux Device Driver》——调试技术

内核中的调试支持 编译内核 1.获取内核源码,解压至/usr/src # tar xf linux-3.13.5.tar.xz -C /usr/src # ln -sv /usr/src/linux-3.13.5 /usr/src/linux 2.配置内核特性(选择一种方法就可以了) make config:遍历选择所要编译的内核特性 make allyesconfig:配置所有可编译的内核特性 make allnoconf

sunr_的博客 705

Linux Device Drivers / Linux 设备驱动程序(第三版)

Linux驱动基础知识,强烈推荐阅读Linux Device Driver / Linux 设备驱动程序(第三版),附件含中英文版本。

Linux Device Drivers-第三章 字符设备驱动程序

看了半个月了,但感觉自己这样毫无目标的看效率太低,网上看到大佬十年前就看英文原版书籍了,同时在做读书笔记,,,实在是惭愧

“Struggle”的博客 1087

Geneformer实战指南:基于Hugging Face Transformers的基因序列分类模型解析

本文详细解析了基于Hugging Face Transformers的Geneformer模型在基因序列分类任务中的应用。通过介绍模型架构、数据处理流程和实战案例,帮助生物信息学研究者掌握这一前沿技术,实现高效的基因表达数据分析与分类。

weixin_28224217的博客 582

一文读懂如何在 Linux 中编写设备驱动程序

我现在将继续修改我刚刚创建的驱动程序,以开发一个真正在真实设备上执行操作的驱动程序。我将使用简单而无处不在的计算机并行端口,驱动程序将被称为 parlelport(并行端口)。译者:时至今日,并口已不常见,而非作者所说的那样“无处不在”,我本来想找替代方法的,比如串口的 DTR 或者 RTS 脚给它置高电平,但是转念一想,现在的电脑上串口也不常见了,大家真的要实验,可能只能去买一个 ARM 开发板,或者其它什么实验板来玩一玩了。并口(并行端口)实际上是一种用于数字信息输入输出的设备。...

found的专栏 3624

MATLAB编程实战:通过SCPI命令高效读取普源示波器数据

本文详细介绍了如何利用MATLAB通过SCPI命令高效读取普源示波器数据,实现自动化测试与数据分析。文章从硬件连接到软件配置,再到核心代码编写与数据解析,提供了完整的实战指南,帮助工程师和科研人员摆脱手动操作,直接从示波器内存中精准读取数据,并利用MATLAB进行FFT频谱分析,大幅提升工作效率。

weixin_29176179的博客 545

绕过ROS2!在RDK X5上直接用Python调用海康相机C++ SDK的避坑指南

本文详细介绍了在RDK X5上绕过ROS2,直接使用Python调用海康相机C++ SDK的轻量化方案。通过Cython构建Python绑定,提取海康相机SDK核心组件,实现高效图像采集。文章涵盖环境准备、Cython接口设计、编译系统配置及性能优化技巧,特别适合ARM64平台开发者。

weixin_33712987的博客 249

2. Linux Device Drivers -- 读书笔记(一)

linux device driver

weixin_42405103的博客 842

全志 T527_Android13 编译 [ 避坑必看 ]

Swap 概念: Linux中Swap(即:交换分区),类似于Windows的虚拟内存,就是当内存不足的时候,把一部分硬盘空间虚拟成内存使用,从而解决内存容量不足的情况。它的功能就是在内存不够的情况下,操作系统先把内存中暂时不用的数据,存到硬盘的交换空间,腾出内存来让别的程序运行。当输入编译命令make -j16 的时候,会有如下提示,这是官方建议通过减少编译线程来解决编译时消耗内存过大的问题。Android 13 系统的编译流程,编译一共分为两部分:内核编译与 Android 编译。

公众号:嵌入式分享 2111

linux设备驱动——bus、device、driver加载顺序与匹配流程

Linux设备驱动相关知识

holly的专栏 9518

【ESP 保姆级教程】玩转emqx数据集成篇④ ——数据桥接之HTTP服务

主要是学习数据桥接功能以及构建自己的http服务器,这是一个非常有用的功能。包括各种传感器上报基本上都需要数据桥接功能支持,所以还是希望认真学习这一块开发,然后结合数据库存储等等知识点进行进一步学习。

单片机菜鸟哥的博客 1307

18006.STM32通过SPI读取LAN9253数据

【代码】18006.STM32通过SPI读取LAN9253数据。

写给自己的笔记 556

Linux Device Drivers-第四章 调试技术

Linux 程序调试方法,学会通过监视调试如控制printk,学会使用各种调试工具如gdb。

“Struggle”的博客 779

SAP Clean Core 对传统 ABAP 开发人员来说意味着什么:机遇和挑战

SAP Clean Core是一种战略方法,旨在优化和现代化 SAP S/4HANA 系统,通过尽量减少定制,确保核心系统的稳定性、高效性和对云环境的兼容性。Clean Core 作为一种设计思路,致力于让 ERP 系统的核心功能保持简洁、规范,避免不必要的复杂化,最终维持一个标准化的核心,使系统更容易升级、性能更优越,同时支持快速的创新能力。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 610

《Linux Device Drivers》第一章 设备驱动程序简介——note

设备驱动程序的作用驱动程序的编写实际上都可以分成两部分 需要提供什么功能(机制)如何使用这些功能(策略) 不带策略的驱动程序包括一些典型的特征 同时支持同步和异步操作驱动程序能够被多次打开充分利用硬件特性 内核功能划分 功能模块 进程管理 创建进程销毁进程进程间通信 信号管道 内存管理 虚拟地址空间 文件系统 Unix的每个对象都可以当作

Linux/Android/AI 39万+

华为OD机试 - 商品推荐多属性排序 - 数组(Python/JS/C/C++ 双机位A卷 100分)

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。双十一来临,小王准备买某个购物平台买坚果。在输入坚果时,页面默认按照综合推荐列表。小王想知道这个综合排序时如何完成的,于是便开始思考算法题。经过一番操作后,完成它的多个关键词排序算法。希望你给小王提供一份正确的排序结果,验证其实现算法结果的准确性

学Java,找哪吒 622

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Swift 集合类型完全指南:数组、集合与字典的创建、操作与遍历(《Swift 编程语言》中文版详解)

本篇文章以《Swift 编程语言》(The Swift Programming Language,简称 TSPL)中文版仓库中的「集合类型」章节为主体,系统讲解 Swift 的三种主要集合类型——**数组(Array)**、**集合(Set)** 与 **字典(Dictionary)**:从创建、访问、修改到遍历的完整 API 用法,再到集合运算、成员关系判定等进阶话题。读完本文,你将掌握 Swi

gitblog_01298的博客 782

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

CANN/asc-devkit: bfloat16转int32 API

| 产品 | 是否支持 | | :-----------| :------: | | <term>Atlas A3 训练系列产品/Atlas A3 推理系列产品</term> | √ | | <term>Atlas A2 训练系列产品/Atlas A2 推理系列产品</term> | √ | ## 功能说明 将bfloat16_t类型数据转换为int32_t类型,并支持

gitblog_00008的博客 541

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Linux 设备驱动开发(一)

Linux 内核是一款复杂、可移植、模块化且广泛使用的软件,约 80%的服务器和超过一半的全球嵌入式系统都在运行该软件。设备驱动程序在 Linux 系统性能方面起着至关重要的作用。随着 Linux 成为最受欢迎的操作系统之一,对于开发个人设备驱动程序的兴趣也在稳步增长。设备驱动程序是用户空间和设备之间的链接,通过内核。本书将从两章开始,帮助您了解驱动程序的基础知识,并为您在 Linux 内核中的漫长旅程做好准备。

龙哥盟 1530

Linux Device Drivers-第五章 并发和竞争情况

结合LinuxDeviceDriver书籍内容,总结内核中发生并发和竞争时,使用到的信号量和各种锁机制的原理及API。

“Struggle”的博客 946

Linux设备模型5

Linux设备模型5(基于Linux6.6)---device和device_driver介绍

ListQ的博客 1371
上一篇: 《Linux Device Drivers》第五章 并发和竞态——note
下一篇: 《Linux Device Drivers》 第七章 时间、延时及延缓操作——note
pingfengluo
博客等级 码龄14年 260粉丝 48原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值