字符设备驱动程序的读写操作详解

字符设备驱动程序实现读写功能 这是字符设备驱动的经典程序,globalmem可以实现对设备的读写操作,很有意思,希望大神们多多指教。 立即下载

前言

        在 Linux 内核开发中,用户空间和内核空间的数据传输是至关重要的。由于两者有不同的访问权限和地址空间,直接使用 memcpy 进行传输是不安全的。为解决这个问题,内核提供了专门的函数 copy_to_user 和 copy_from_user。本博客将详细介绍这些函数的使用场景、参数和返回值,并通过实际代码示例展示如何在设备驱动开发中实现安全的数据传输。此外,还会讨论 put_user 和 get_user 函数,帮助读者更好地理解和掌握 Linux 内核中用户空间和内核空间之间的数据传输方法。

用户空间和内核空间的数据传输

        在 Linux 内核开发中,用户空间和内核空间的数据传输是一个重要的概念。由于用户空间和内核空间具有不同的访问权限和地址空间,直接使用 memcpy 函数进行数据传输是不安全的。为了确保数据传输的安全性和合法性,内核提供了专门的函数:copy_to_user 和 copy_from_user。

用户空间数据传输函数 copy_to_user

copy_to_user 函数用于将数据从内核空间复制到用户空间,确保在复制过程中不会违反内存访问权限。

使用场景

  • 设备驱动程序:通常在读操作中使用,将设备数据从内核空间复制到用户空间缓冲区。
  • 系统调用实现:在实现系统调用时,用于将数据从内核传递给用户进程。

unsigned long copy_to_user(void __user *to, const void *from, unsigned long n);

  • 参数:
    • void __user *to:指向用户空间目标缓冲区的指针。
    • const void *from:指向内核空间源缓冲区的指针。
    • unsigned long n:要复制的字节数。
  • 返回值:
    • 成功时返回未能成功复制的字节数,通常为0。
    • 失败时返回未能成功复制的字节数。如果整个复制操作失败,返回值等于参数 n。

用户空间数据传输函数 copy_from_user

copy_from_user 函数用于将数据从用户空间缓冲区复制到内核空间,确保在数据传输过程中不会违反内存访问权限。

使用场景

  • 设备驱动程序:通常在写操作或 ioctl 操作中使用,将用户提供的数据从用户空间复制到内核空间缓冲区。
  • 系统调用实现:在实现系统调用时,用于接收从用户进程传递到内核的数据。

unsigned long copy_from_user(void *to, const void __user *from, unsigned long n);

  • 参数:
    • void *to:指向内核空间目标缓冲区的指针。
    • const void __user *from:指向用户空间源缓冲区的指针。
    • unsigned long n:要复制的字节数。
  • 返回值:
    • 成功时返回未能成功复制的字节数,通常为0。
    • 失败时返回未能成功复制的字节数。如果整个复制操作失败,返回值等于参数 n。

简单变量的数据传输

在 Linux 内核中,put_user 和 get_user 函数用于在内核空间和用户空间之间传输简单变量的数据。这些函数用于确保安全的数据传输,并防止内核因非法内存访问而崩溃。

函数 put_user

put_user 函数用于将一个简单变量从内核空间复制到用户空间。

int put_user(type x, type __user *ptr);

  • 参数:
    • type x:要复制到用户空间的变量值。
    • type __user *ptr:指向用户空间目标地址的指针。
  • 返回值:
    • 成功时返回0。
    • 失败时返回一个负的错误码,例如 -EFAULT,表示发生了非法内存访问。

函数 get_user

get_user 函数用于从用户空间复制一个简单变量到内核空间。

int get_user(type x, const type __user *ptr);

  • 参数:
    • type x:用于存储从用户空间复制的变量值。
    • const type __user *ptr:指向用户空间源地址的指针。
  • 返回值:
    • 成功时返回0,并将变量值复制到 x。
    • 失败时返回一个负的错误码,例如 -EFAULT,表示发生了非法内存访问。

读写操作实现

在设备驱动开发中,实现读写操作是一个关键任务。下面将详细介绍读写操作的实现方法。

读操作实现

read 系统调用

ssize_t read(int fd, void *buf, size_t count);

  • 功能:用于从文件或设备中读取数据到用户空间的缓冲区中。
  • 参数:
    • int fd:文件描述符,标识要读取的文件或设备。
    • void *buf:指向用户空间的缓冲区,用于存储从文件或设备中读取的数据。
    • size_t count:要读取的字节数。
  • 返回值:
    • 成功时返回实际读取的字节数。
    • 返回值为0表示已到达文件末尾(EOF)。
    • 出错时返回 -1,并设置 errno 以指示具体的错误码。

文件操作的 read 方法

ssize_t xxx_read(struct file *filp, char __user *pbuf, size_t count, loff_t *ppos);

  • 功能:读取设备产生的数据。
  • 参数:
    • struct file *filp:指向 open 产生的 struct file 类型的对象。
    • char __user *pbuf:指向用户空间一块内存,用来保存读到的数据。
    • size_t count:用户期望读取的字节数。
    • loff_t *ppos:指示读取的起始位置。
  • 返回值:成功返回本次成功读取的字节数,失败返回 -1。

数据读取的过程

  1. 用户空间到内核空间的请求传递:

    • 当应用程序调用 read 系统调用时,数据参数(fd, buf, count)从用户空间的缓冲区通过系统调用接口传递到内核。

    • 内核根据文件描述符找到对应的文件对象和文件操作方法。

  2. 内核空间数据准备:

    • 内核中的文件操作方法 read 会从设备或内核缓冲区中读取数据。

    • 在 mychar_read 函数中,首先确定要读取的字节数,确保不会超过当前缓冲区中的数据量。

    • 然后,调用 copy_to_user 函数,将数据从内核缓冲区 mydev_buf 复制到用户空间缓冲区 buf。

  3. 内核空间到用户空间的数据传输:

    • 使用 copy_to_user 函数将数据从内核缓冲区复制到用户空间缓冲区,并返回读取的字节数。确保数据传输的安全性和合法性,防止非法内存访问。

    • 最后,将剩余的缓冲区数据前移,更新缓冲区长度 curlen。

写操作实现

在进行写入操作时,从应用程序写入到内核的数据通常存放在内核的缓冲区或设备驱动程序中为该设备分配的内存区域中。

write 系统调用

ssize_t write(int fd, const void *buf, size_t count);

  • 功能:用于将数据从用户空间缓冲区写入到指定文件或设备。
  • 参数:
    • int fd:文件描述符,标识要写入的文件或设备。
    • const void *buf:指向用户空间缓冲区的指针。
    • size_t count:要写入的字节数。
  • 返回值:
    • 成功时返回实际写入的字节数。
    • 失败时返回 -1,并设置 errno 以指示具体的错误码。

文件操作的 write 方法

ssize_t xxx_write(struct file *filp, const char __user *pbuf, size_t count, loff_t *ppos);

  • 功能:向设备写入数据。
  • 参数:
    • struct file *filp:指向 open 系统调用产生的 struct file 类型的对象。
    • const char __user *pbuf:指向用户空间的一块内存。
    • size_t count:用户期望写入的字节数。
    • loff_t *ppos:指示写入的起始位置。
  • 返回值:成功返回实际写入的字节数,失败返回 -1。

数据写入的过程

  1. 用户空间到内核空间的请求传递:

    • 当应用程序调用 write 系统调用时,数据参数(fd, buf, count)从用户空间的缓冲区通过系统调用接口传递到内核。

    • 内核根据文件描述符找到对应的文件对象和文件操作方法。

  2. 内核空间数据接收:

    • 内核中的文件操作方法 write 会为数据写入做准备。

    • 在 mychar_write 函数中,首先确定要写入的字节数,确保不会超过内核缓冲区的剩余空间。

  3. 用户空间到内核空间的数据传输:

    • mychar_write 函数调用 copy_from_user 函数将数据从用户空间缓冲区 buf 复制到内核缓冲区 mydev_buf,并返回成功复制的字节数。

    • 确保数据传输的安全性和合法性,防止非法内存访问。

  4. 内核空间数据存储:

    • 更新内核缓冲区长度 curlen,记录当前存储的数据量。

    • 如果有需要,执行其他设备相关操作(如触发硬件事件或更新设备状态)。

  5. 内核数据存放位置:

    • 内核缓冲区:对于普通文件,数据会被放入文件系统的内核缓冲区(如页缓存)。这些缓冲区临时存储数据,最终会被写入磁盘。

    • 设备驱动程序的缓冲区:对于字符设备或块设备,数据会被存放在设备驱动程序中分配的缓冲区或内存区域中。例如,在字符设备驱动程序中,可以是一个全局的内核缓冲区。

    • 网络设备:对于网络设备,数据会被存放在网络协议栈的缓冲区中,然后通过网络接口发送出去。

示例

驱动示例

下面是一个完整的字符设备驱动示例,展示了如何实现读写操作。

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h> // 包含copy_to_user和copy_from_user函数

#define BUF_LEN 100

int major = 11;
int minor = 0;
int mychar_num = 1;

struct cdev mydev; // 字符设备结构体

char mydev_buf[BUF_LEN]; // 设备驱动缓冲区
int curlen = 0; // 当前缓冲区长度

// 打开设备文件的函数
int mychar_open(struct inode *pnode, struct file *pfile)
{
    printk("mychar_open is called\n");
    return 0;
}

// 关闭设备文件的函数
int mychar_close(struct inode *pnode, struct file *pfile)
{
    printk("mychar_close is called\n");
    return 0;
}

// 读取设备数据的函数
ssize_t mychar_read(struct file *pfile, char __user *puser, size_t count, loff_t *p_pos)
{
    int size = 0;
    int ret = 0;

    // 判断要读取的字节数是否大于当前缓冲区中的数据量
    if(count > curlen)
    {
        size = curlen;
    }
    else
    {
        size = count;
    }

    // 将数据从内核空间复制到用户空间
    ret = copy_to_user(puser, mydev_buf, size);
    if(ret)
    {
        printk("copy_to_user failed\n");
        return -1;
    }

    // 将缓冲区剩余数据前移
    memcpy(mydev_buf, mydev_buf + size, curlen - size);

    // 更新当前缓冲区长度
    curlen -= size;
    return size;
}

// 写入设备数据的函数
ssize_t mychar_write(struct file *pfile, const char __user *puser, size_t count, loff_t *p_pos)
{
    int size = 0;
    int ret = 0;

    // 判断缓冲区是否有足够的空间容纳要写入的数据
    if(count > (BUF_LEN - curlen))
    {
        size = BUF_LEN - curlen;
    }
    else
    {
        size = count;
    }

    // 将数据从用户空间复制到内核空间
    ret = copy_from_user(mydev_buf + curlen, puser, size);
    if(ret)
    {
        printk("copy_from_user failed\n");
        return -1;
    }

    // 更新当前缓冲区长度
    curlen += size;
    return size;
}

// 文件操作函数集
struct file_operations myops = {
    .owner = THIS_MODULE,
    .open = mychar_open,
    .release = mychar_close,
    .read = mychar_read,
    .write = mychar_write,
};

// 模块初始化函数
int __init mychar_init(void)
{
    int ret = 0;
    dev_t devno = MKDEV(major, minor);

    // 申请设备号
    ret = register_chrdev_region(devno, mychar_num, "mychar");
    if(ret)
    {
        ret = alloc_chrdev_region(&devno, minor, mychar_num, "mychar");
        if(ret)
        {
            printk("get devno failed\n");
            return -1;
        }
        major = MAJOR(devno); // 设置主设备号
    }

    // 给struct cdev对象指定操作函数集
    cdev_init(&mydev, &myops);

    // 将struct cdev对象添加到内核对应的数据结构里
    mydev.owner = THIS_MODULE;
    cdev_add(&mydev, devno, mychar_num);

    return 0;
}

// 模块退出函数
void __exit mychar_exit(void)
{
    dev_t devno = MKDEV(major, minor);
    cdev_del(&mydev);
    unregister_chrdev_region(devno, mychar_num);
}

MODULE_LICENSE("GPL");

module_init(mychar_init);
module_exit(mychar_exit);

测试程序

为了验证上述字符设备驱动程序的功能,可以编写一个简单的用户空间测试程序 testmychar_app.c。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
    int fd = -1;            // 文件描述符
    char buf[8] = "";       // 读取缓冲区

    // 检查命令行参数是否足够
    if(argc < 2)
    {
        printf("the argument is too few\n"); // 提示参数过少
        return 1;                            // 返回错误码1
    }

    // 打开指定的文件或设备
    fd = open(argv[1], O_RDWR);

    // 检查文件是否成功打开
    if(fd < 0)
    {
        printf("open %s failed\n", argv[1]); // 提示打开文件失败
        return 2;                            // 返回错误码2
    }

    // 向文件或设备写入数据
    write(fd, "hello", 6);

    // 从文件或设备读取数据
    read(fd, buf, 8);
    printf("read buf: %s\n", buf);            // 打印读取到的数据

    // 关闭文件描述符
    close(fd);
    fd = -1;

    return 0;
}

运行测试程序

在运行测试程序之前,需要确保设备文件存在并具有正确的权限。

# 创建设备文件 sudo mknod /dev/mychar c 11 0 # 修改设备文件权限 sudo chmod 666 /dev/mychar

然后编译并运行测试程序:

gcc testmychar_app.c -o testmychar_app ./testmychar_app /dev/mychar

结论

通过上述代码和测试程序,我们实现了一个简单的字符设备驱动程序,并验证了读写操作的正确性。以下是一些关键点:

  1. 安全的数据传输:使用 copy_to_user 和 copy_from_user 确保内核和用户空间之间的数据传输是安全的。
  2. 读写操作实现:通过实现字符设备的 read 和 write 方法,实现设备数据的读取和写入。
  3. 测试验证:通过编写用户空间测试程序,验证字符设备驱动程序的功能和稳定性。
BLE天线设计避坑:NRF52832官方50欧姆阻抗匹配的3个常见误区 本文深入解析NRF52832蓝牙SoC天线设计中的常见误区,重点探讨50欧姆阻抗匹配的3个关键问题:PCB板材介电常数差异、匹配元件寄生参数及VSWR测试。通过实测数据和优化方案,帮助工程师规避设计陷阱,提升BLE通信性能。 阅读详情

相关推荐

VScode - 从入门到精通:高效开发环境搭建指南

本文是一份全面的VSCode高效开发环境搭建指南。从选择理由、安装配置、核心插件推荐到个性化设置与高效技巧,详细讲解了如何将这款轻量级编辑器武装成强大的开发工具。重点介绍了GitLens、Prettier、Live Server等必备插件,以及通过用户设置、代码片段和快捷键打造专属高效工作流的方法,帮助开发者从入门到精通。

weixin_27734811的博客 426

字符设备驱动读写操作实现

字符设备驱动:读操作实现、写操作实现

qq_36091214的博客 595

horizon之为connection服务器配置证书

打开connection1服务器(connection2 同connection1)再输入connection1的IP地址 可通过域名和IP地址进行登录。这时候用域名登录就发现证书已经没有警告了。win+R 调出“运行”,输入mmc。connection2 同上。如果还有报错请重启一下服务器。打开connection1。可以把这个先删掉 没用。打开DC_01服务器。右键选择证书颁发机构。友好名称只能是vdm。重启之后就没有报错了。

送个祝福给小豪的博客 2960

简单字符设备文件的实现(包含文件的读写和逻辑梳理)

240// 主设备号#define MYNAME "my_chrdev" // 设备名称// 定义一个缓存数组,用于内核接收数据// 定义一个字符设备结构体// 用于保存主设备号kbuf:这个数组在内核中被分配,并且在内核模块的整个生命周期中都可以访问。类型:一种表示字符设备的结构体,可以通过它来管理字符设备的操作。

一扣解千愁的博客 1305

微信中调起支付宝支付

微信中调用支付宝支付,首先我们知道微信是不能直接调用支付宝的,所以我们需要使用一个中间页提示用户在浏览器中打开,然后进行网页支付或打开app支付。以下为详细唤起支付宝的步骤、业务代码以及相关页面图。 如有问题欢迎评论留言,看到定回复哦^_^\(^o^)/~ 一、微信中唤起支付宝,有几个步骤: 1、中间页引导用户在浏览器中打开去唤起支付宝。 2、浏览器中打开支付宝或app中打开支付宝。 3...

han_calligrapher的博客 2万+

【教程4>第5章>第19节】基于Gardner环的位同步系统MATLAB仿真与带时偏基带数据导出

由于在FPGA中,时偏的影响主要是由系统收发两端晶振的不同步带来的,所以在仿真测试阶段,很难直接通过FPGA来模拟这个因素,所以我们采用MATLAB模拟带时偏的基带输入信号,并将其导出,由FPGA调用作为测试信号源。可以看到,同步之后(图3)相对于带时偏的基带信号(图2),其更接近标准的数据(图1),且抖动较小。订阅过的朋友可以复习下这个课程,没有订阅的朋友,也可以直接复制如下的程序进行仿真测试。上述程序中,加入时偏的基带信号,通过子函数。同步之后,可以恢复出标准的QPSK星座图。

FPGA/MATLAB学习教程/源码/项目合作开发 520

字符设备驱动开发基础—从驱动中进行读写操作

本文主要介绍的是 如何通过Linux驱动模块进行设备的模拟读写操作。

weixin_46999174的博客 938

QProgressBar:常用接口、样式表及自定义进度条实现

在Qt开发中,QProgressBar 是一个非常常用的控件,用于显示任务的进度。无论是文件下载、数据处理还是其他耗时操作,QProgressBar 都能直观地展示当前进度。本文将详细介绍QProgressBar 的使用方法,包括常用接口、样式表设置,并额外补充一个自定义进度条的C++实现。

u011186532的专栏 1012

字符设备(1)读写

/* struct cdev { struct kobject kobj; struct module *owner; //一般初始化为THIS_MODULE const struct file_operations *ops; //文件操作结构体 struct list_head list; dev_t dev; //设备号 unsigned int count; //添加的设备个数

专业减肥计划 934

提高RFID检测距离以及检测速度的方法总结

摘要:提高RFID检测距离需优化阅读器功率、标签灵敏度、天线设计及频段选择,同时减少环境干扰;提升检测速度则需改进防碰撞算法、增强并行处理能力、精简数据传输。实际应用需平衡两者关系,如物流仓储采用UHF频段、高增益天线和动态Q算法实现远距离高速读取,ETC系统则通过微波频段和高速调制实现超远距离快速识别。不同场景需针对性优化硬件配置和系统参数。

start_up_go的博客 292

fanuc机器人I/O分配

FANUC机器人在和其他外部设备进行通讯时,需要对信号进行配置。 在机器人处于UOP自动分配状态时,系统会自动检索已配对设备,并分配相应的机架号。 当我们需要手动对信号进行分配时,可参考以下机架号进行配置。 不同的通讯协议对应的机架号不同,外部通讯协议常用的机架号参考下表: 序号 机架号 通讯类型 1 0 Process I/O 2 1-15

haier123888的博客 1万+

字符设备的读写

在应用程序看来,字符设备只是一个设备文件,应用程序可以像操作普通文件一样对硬件设备进行操作。应用层对设备的操作都在设备驱动程序的file_operations结构中有对应的接口,比如应用层的read函数对应驱动层的file_operations-> read,而应用层的write函数对应驱动层的file_operations-> write。本节介绍字符设备内核空间与用户空间数据交互的方法。

浩瀚之水的专栏 2627

台球 PCOL:极致物理还原的网页斯诺克引擎(附源码深度解析)

*完整源码地址**:[https://github.com/billiards/pcol-core](https://github.com/billiards/pcol-core)(包含详细文档与示例)通过这个项目,我们不仅创建了一个游戏,更构建了一个**可扩展的物理引擎框架**,为网页端复杂物理模拟开辟了新的可能性。**在线体验**:[https://pcol.billiards](https://pcol.billiards)(支持移动端触控操作)clone.velocity.x *= -0.92;

Loving_enjoy的博客 2797

操作系统实验·字符设备驱动程序

实验内容 编写一个简单的字符设备驱动程序,该字符设备并不驱动特定的硬件, 而是用内核空间模拟字符设备,要求该字符设备包括以下几个基本操作,打开、读、写和释放,并编写测试程序用于测试所编写的字符设备驱动程序。在此基础上,编写程序实现对该字符设备的同步操作。 相关知识 设备驱动程序 设备驱动程序是内核和硬件设备之间的接口,设备驱动程序屏蔽硬件细节,且设备被映射成特殊的文件进行处理。每个设备都对应一个文件名,在内核中也对应一个索引节点,应用程序可以通过设备的文件名来访问硬件设备。Linux 为文件和设备提供了一致

hushrush的博客 1万+

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

字符设备驱动程序

本章的目标是编写一个完整的字符设备驱动程序。由于这类驱动程序适合于大多数简单的硬件设备,我们首先开放一个字符设备驱动程序。字符也相对比较好理解,比如说块设备驱动程序。我们的最终目标是写一个模块化的字符设备驱动程序,但本章我们不再讲述有关模块化的问题。本章通篇都是从一个真实的设备驱动程序截取出的代码块:这个设备就是scull,是“Simple Character Utility for Loadin

iu_81的专栏 2683

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

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

linux字符设备驱动程序

linux系统中万物皆文件,驱动程序加载后会在/dev目录下生成一个对应的文件,如/dev/led。应用程序就是先用open打开该文件,用write控制led的亮灭,用read读取led的亮灭,用完之后用close关闭该文件。这里需要注意的是,应用程序运行在用户空间,驱动程序运行在内核空间。应用程序必须使用一个叫做“系统调用”的方法来实现从用户空间“陷入”到内核空间,这样才能实现对底层驱动的操作。一个open函数执行的过程如下。

m0_71262188的博客 1338

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

linux简单的字符设备驱动程序

要求:掌握添加设备驱动程序的方法 内容: 采用模块方法,添加一个新的设备驱动程序。 要求添加字符设备的驱动。 编写一个应用程序,测试添加的驱动程序。 <!-- p {margin-bottom:0.21cm} --> linxu系统中,在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的

朱胜本的专栏 1万+

Linux字符设备驱动程序解析

Linux下的设备驱动程序被组织为一组完成不同任务的函数的集合,通过这些函数使得linux的设备操作犹如文件一般。在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作,如open()、close()、read()、write() 等。Linux主要将设备分为二类:字符设备和块设备。字符设备是指设备发送和接收数据以字符的形式进行;而块设备则以整个数据缓冲

kyovs的专栏 834

Linux字符设备驱动程序

Linux字符设备驱动程序是每个驱动开发工程师必会的框架。

YIVIES 1320

字符设备驱动程序编写基础

《字符设备驱动程序编写基础》 本文档的Copyleft归rosetta所有,使用GPL发布,可以自由拷贝、转载,转载时请保持文档的完整性。 参考资料:《Linux设备驱动程序 第三版》,scull源码,Linux内核源码 来源:http://blog.youkuaiyun.com/rosetta/article/details/7563606   本文写了字符设备驱动编写的基础知识,以自己学习

终身学习的程序猿 4437

掌握Linux字符设备驱动程序的核心要点

掌握Linux字符设备驱动程序的核心要点

探索C++编程的奥秘,分享深入的技术见解和实践,旨在激发读者创造力与解决问题的思维。 1202

linux 字符设备驱动程序原理

1. 理解驱动程序 由于unix的万物皆文件的思想,底层的设备也用特殊文件类型,设备文件来操作,通过读写设备文件就可以读写设备内存或者设备端口了,因此需要一个在虚拟文件系统和底层设备之间的一个适配器,这就是设备驱动程序,用于粘合虚拟文件系统和底层的设备,提供上层的虚拟文件系统统一的接口,并且管理和底层设备的交互。 字符设备可以通过一种比较简单的方式管理,因为不需要I/O调度、底层同步、重排请求

lonewolfxw的专栏 1302

linux设备驱动程序第二版 字符设备驱动程序

第3章 字符设备驱动程序本章的目标是编写一个完整的字符设备驱动程序。由于这类驱动程序适合于大多数简单的硬件设备,我们首先开放一个字符设备驱动程序。字符也相对比较好理解,比如说块设备驱动程序。我们的最终目标是写一个模块化的字符设备驱动程序,但本章我们不再讲述有关模块化的问题。本章通篇都是从一个真实的设备驱动程序截取出的代码块:这个设备就是scull,是“Simple Character Ut

menuconfig的专栏 1874
上一篇: 从系统调用到设备驱动:详解open、syscall_open和drv_open
下一篇: ioctl操作实现的原理
Raymond430
博客等级 码龄7年 91粉丝 23原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值