社区首页 >问答首页 >带循环缓冲器的字符驱动器

带循环缓冲器的字符驱动器
EN

Stack Overflow用户
提问于 2015-05-09 17:03:18
回答 1查看 3K关注 0票数 10

我正在学习设备驱动程序编程,我已经创建了一个简单的字符驱动程序,其中我从一个用户空间应用程序传递数据并将其存储在内核空间循环缓冲区中,然后从另一个用户空间应用程序再次读取这个循环缓冲区。

我使用的是linux内核版本3.3.6

我的驱动程序代码是:

代码语言:javascript
代码运行次数:0
复制
/* A simple character driver program to pass some data from user space and storing that on kernel circular buffer and reading back it on user space */

#include<linux/kernel.h>
#include<linux/init.h>
#include<linux/module.h>
#include<linux/vmalloc.h>
#include<linux/fs.h>
#include<linux/major.h>
#include<linux/cdev.h>
#include<asm/uaccess.h>
#include<linux/slab.h>
#include<linux/device.h>
#include<linux/types.h>
#include<linux/kdev_t.h>
#include<linux/wait.h>
#include<linux/sched.h>
#include<linux/circ_buf.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("C-DAC");
#define MAX_DEVICE 2
#define KERN_BUFF_SIZE 1
#define DRIVER_NAME "ass3q1" 

int my_open(struct inode *inode, struct file *filp);
ssize_t my_write(struct file *filp, const char __user *usr_buff, size_t count, loff_t *ppos);
ssize_t my_read(struct file *filp, char __user *usr_buf, size_t count, loff_t *ppos);
int my_release(struct inode *inode, struct file *filp);
long my_ioctl(struct file *filp, unsigned int cmd,unsigned long arg);


/* DEFINE A DEVICE SPECIFIC DATA */
typedef struct privatedata1
{
    int minor_num;
    struct cdev mycdev;
    struct circ_buf KERN_BUFF;
    int KERN_SIZE;
//  char KERN_BUFF[KERN_BUFF_SIZE];
}my_privatedata;

my_privatedata devices[MAX_DEVICE];

/* DECLARE THE REQUIRED VARIABLES */
int major;
int minor=1;
dev_t device_num;

struct class *my_class;
struct device *my_device;

/* DEFINE THE FILE OPERATIONS STRUCTURE OF THE CHAR DRIVER */
struct file_operations my_fops={
    .owner      = THIS_MODULE,
    .open       = my_open,
    .write      = my_write,
    .read       = my_read,
    .release    = my_release,
    .unlocked_ioctl = my_ioctl,
};


/* INITIALISATION FUNCTION */
static int __init my_init(void)
{
    int i;
    int res;
    printk("\nI am in Init Function");
    /* DYNAMICALLY DEVICE NUMBER */
    res = alloc_chrdev_region(&device_num,minor,MAX_DEVICE,DRIVER_NAME);
    if(res<0)
    {
        printk("\nRegister Device Num generation failed");
        return -1;
    }
    major = MAJOR(device_num);

    my_class = class_create(THIS_MODULE,DRIVER_NAME);
    if(my_class == NULL)
    {
        printk("\nClass creation failed");
        return -1;
    }

    for(i=0; i<MAX_DEVICE; i++)
    {
        device_num = MKDEV(major, minor + i);
        cdev_init(&devices[i].mycdev,&my_fops);     //registration of device
        cdev_add(&devices[i].mycdev,device_num,1);  //attachment of device

        /* CREATE DEVICE NODES IN /dev/ DIRECTORY */
        my_device = device_create(my_class,NULL,device_num,NULL,"sample_cdev%d",i);     
        if(my_device == NULL)
        {
            class_destroy(my_class);
            printk("\nDevice creation failed");
            return -1;
        }

        devices[i].minor_num = minor+i;
    }
    return 0;
}

static void __exit my_exit(void)
{
    int i;

    printk("\nI am in Exit Function");
    /* REMOVE DEVICES AND NODES */
    for(i=0; i<MAX_DEVICE; i++)
    {
        device_num = MKDEV(major, minor + i);
        cdev_del(&devices[i].mycdev);
        device_destroy(my_class, device_num);
    }

    /* DESTROY CLASS */
    class_destroy(my_class);

    /* UNREGISTER DEVICE WITH KERNEL */
    device_num = MKDEV(major, minor);
    unregister_chrdev_region(device_num, MAX_DEVICE);
}

/* DEVICE OPEN METHOD */
int my_open(struct inode *inode, struct file *filp)
{
    my_privatedata *dev = container_of(inode->i_cdev, my_privatedata, mycdev);
    filp->private_data = dev;
    dev->KERN_SIZE = 4096;
    printk("\nIn character driver open function device node %d", dev->minor_num);
    return 0;
}

/* DEVICE WRITE METHOD */
ssize_t my_write(struct file *filp, const char __user *usr_buff, size_t count, loff_t *ppos)
{
    my_privatedata *dev = filp->private_data;

    if(CIRC_SPACE(dev->KERN_BUFF.head, dev->KERN_BUFF.tail, dev->KERN_SIZE) >= 1)
    {
        int i;
        char ch;
        for(i=0; i<count; i++)
        {
            get_user(ch, &usr_buff[i]);
            dev->KERN_BUFF.buf[dev->KERN_BUFF.head] = ch;
            printk("\nIn character driver write function and value of KERN_BUFF is: %s", dev->KERN_BUFF.buf);
            dev->KERN_BUFF.head = (dev->KERN_BUFF.head + 1) & (dev->KERN_SIZE-1);
        }
    }   
    else
    {
        printk("\nCopy from user to kernel space failed");
        return -EFAULT;
    }
    return 0;
}

/* DEVICE READ METHOD */
ssize_t my_read(struct file *filp, char __user *usr_buf, size_t count, loff_t *ppos)
{
    my_privatedata *dev = filp->private_data;
    int res;
    printk("\nI am in character driver read function");
    dev->KERN_BUFF.buf = "Bye Bye";
//  usr_buf = dev->KERN_BUFF.buf;

    res = copy_to_user((char *)usr_buf, (char *)dev->KERN_BUFF.buf, strlen(dev->KERN_BUFF.buf)+1);
    printk("\nData '%s' from kernel buffer to user buffer copied successfully with bytes: %d",dev->KERN_BUFF.buf,strlen(dev->KERN_BUFF.buf));

/*  if(res == 0)
    {
        printk("\nData '%s' from kernel buffer to user buffer copied successfully with bytes: %d",dev->KERN_BUFF.buf,strlen(dev->KERN_BUFF.buf));
        memset(dev->KERN_BUFF.buf, 0, strlen(dev->KERN_BUFF.buf));
        return strlen(dev->KERN_BUFF.buf);
    }
    else
    {
        printk("\nCopy from kernel to user failed");
        return -EFAULT;
    }
*/
    return 0;
}

/* DEVICE RELEASE METHOD */
int my_release(struct inode *inode, struct file *filp)
{
    my_privatedata *dev = filp->private_data;
    printk("\nI am in release function and minor number is %d", dev->minor_num);
    return 0;
}

/* DRIVER IOCTL METHOD */
long my_ioctl(struct file *filp, unsigned int cmd,unsigned long arg)
{
    printk("\nIn Driver ioctl function");
    my_privatedata *dev = filp->private_data;

    switch (cmd)
    {
        case 1:
            {
                int count;
                count = CIRC_CNT(dev->KERN_BUFF.head, dev->KERN_BUFF.tail,dev->KERN_SIZE);
                printk("\nSize of buffer count is %d",count);
                return count;
                break;
            }
        case 2:
            {
                int space;
                space = CIRC_SPACE(dev->KERN_BUFF.head, dev->KERN_BUFF.tail,dev->KERN_SIZE);
                printk("\nSize of buffer count is %d",space);
                return space;
                break;
            }
        default:
            {
                printk("\nNothing to show");
                break;
            }
    }
}

module_init(my_init);
module_exit(my_exit);

我的用户空间写入器应用程序是

代码语言:javascript
代码运行次数:0
复制
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>

int main()
{
    int fd;
    char Ubuff[50], Kbuff[50];

    fd = open("/dev/sample_cdev1", O_RDWR);
    if(fd < 0) {
        perror("Unable to open the device file\n");
        return -1;
    }

    printf("\nPlease enter a string");
    gets(Ubuff);

    /* Write the data into the device */
    write(fd , Ubuff , strlen(Ubuff) + 1);

    close(fd);  
    return 0;
}

我的用户空间阅读器应用是

代码语言:javascript
代码运行次数:0
复制
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>

int main()
{
    int fd;
    char Ubuff[50], Kbuff[50];

    fd = open("/dev/sample_cdev1", O_RDWR);
    if(fd < 0) {
        perror("Unable to open the device file\n");
        return -1;
    }

    /* Read the data back from the device */
    memset(Kbuff , 0 ,sizeof(Kbuff));
    read(fd , Kbuff , sizeof(Kbuff));
    printf("Data from kernel : %s\n", Kbuff);

    close(fd);
    return 0;
}

在my_write函数中,我在以下位置得到内核null指针取消引用错误

代码语言:javascript
代码运行次数:0
复制
            dev->KERN_BUFF.buf[dev->KERN_BUFF.head] = ch;
            printk("\nIn character driver write function and value of KERN_BUFF is: %s", dev->KERN_BUFF.buf);
            dev->KERN_BUFF.head = (dev->KERN_BUFF.head + 1) & (dev->KERN_SIZE-1);

my_read函数似乎不正确,但由于我无法向内核循环缓冲区写入内容,因此无法测试my_read函数。

我做错了什么?

EN

回答 1

Stack Overflow用户

发布于 2015-06-11 13:32:02

我认为问题是你没有在你的循环缓冲区中分配任何空间...dev->KERN_BUFF.buf = kmalloc(...)别忘了释放。你也注册了2个my_private_data,这意味着每个fd都会有自己的my_private_data。我认为您希望生产者和消费者寻址相同的数据。也许你需要一个spin_lock。

另请阅读:CIRCULAR BUFFERS

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30142728

复制
相关文章
gitlab备份与还原
由于gitlab中存放的都是开发人员的工作成果,所以为了保证数据安全,我们会定期对数据进行备份,对gitlab进行备份将会创建一个包含所有库和附件的归档文件。对备份的恢复只能恢复到与备份时的gitlab相同的版本。将gitlab迁移到另一台服务器上的最佳方法就是通过备份和还原。gitlab提供了一个简单的命令行来备份整个gitlab ,并且能灵活的满足需求。
星哥玩云
2022/09/15
1.8K0
gitlab远古版本备份&还原&升级
gitlab 8.5.8版本.参照:https://github.com/sameersbn/docker-gitlab.git.太多年了也没有升级,现在准备备份还原到一个新的服务器然后升级一下。gitlab服务器开始是docker-compose搭建的后面迁移到了kubernetes上(记得当时还是1.14),后面kubernetes 版本持续升级到了1.21。基础环境如下:
对你无可奈何
2023/03/09
1.4K0
gitlab远古版本8.5.8备份&还原&升级
gitlab 8.5.8版本.参照:https://github.com/sameersbn/docker-gitlab.git.太多年了也没有升级,现在准备备份还原到一个新的服务器然后升级一下。gitlab服务器开始是docker-compose搭建的后面迁移到了kubernetes上(记得当时还是1.14),后面kubernetes 版本持续升级到了1.21。基础环境如下:
对你无可奈何
2023/03/09
1.2K0
ghost备份和还原_cgi备份还原
用Ghost手动备份系统,主要是针对组装电脑而言,至于品牌机,它都会有自己的系统恢复工具,所以不在此列。 现在很多人对在使用电脑中出现系统崩溃的故障,都会采取重装系统的办法。 其实重装系统是一件比较麻烦的事。 一切都得从头开始,尤其是安装驱动、应用程序等等,全部再装好需要花费较长的时间。 所以在这里特别建议大家,在安装完操作系统之后,对系统进行手动备份。 这样当系统出现故障不能正常启动时,就可以从光盘或U盘启动,然后将系统还原,省时省力。 现在的操作系统镜像文件都提供有Ghost程序,可以将镜像文件刻录到光盘,也可以用老毛桃制作一个U盘启动盘。
全栈程序员站长
2022/10/04
3.9K0
ghost备份和还原_cgi备份还原
备份还原记
从php爆出漏洞的消息后,我这平日也没光临的小博,竟然跟风去升级了php,还是最新版的5.6版,然后。。。然后502了,当然,理所当然的我不知道问题出在哪里,于是开始了从来没有过的直接下载网站文件和数据库的备份恢复旅程。
空空裤兜
2023/03/03
1.3K0
备份还原记
ghost备份还原详细步骤_ghost一键备份还原
注意点 1: 整个过程中不可动鼠标,使用键盘和触摸板操作。开始备份或还原后中不要动键盘
全栈程序员站长
2022/10/04
3K0
gitlab 备份&恢复
默认 Gitlab 的备份文件会创建在/var/opt/gitlab/backups文件夹中,格式为时间戳_日期_版本号_gitlab_backup.tar,例如:1515031353_2018_01_04_10.3.2_gitlab_backup.tar。 修改备份文件夹,需要修改配置文件/etc/gitlab/gitlab.rb中的:
陈不成i
2021/06/04
1.8K0
xtrabackup 备份+还原简记
1、安装 下载地址:https://www.percona.com/downloads/Percona-XtraBackup-LATEST/
星哥玩云
2022/08/18
9180
elasticsearch数据备份还原[未测试]
1.在浏览器中运行http://XXX.XXX.XXX.XXX:9200/_flush,确保索引数据能保存到硬盘中。 2.原数据的备份。主要是elasticsearch数据目录下的nodes目录的备份。nodes目录为索引数据目录。 3.将原集群中的每个elasticsearch节点下的data目录拷贝至新的elasticsearch数据目录下。
双面人
2019/04/10
1.1K0
驱动备份还原精简工具
作者:matrix 被围观: 1,710 次 发布时间:2013-03-26 分类:兼容并蓄 | 无评论 »
HHTjim 部落格
2022/09/26
9110
驱动备份还原精简工具
MySQL备份还原——AutoMySQLBackup介绍
AutoMySQLBackup是一个开源的MySQL备份脚本。可以说它是一个轻量级的备份方案,AutoMySQLBackup的安装、配置非常简单、方便。AutoMySQLBackup的sourceforge上介绍有如它本身,也非常的简单:
拓荒者
2019/03/11
5.2K0
MySQL备份还原——AutoMySQLBackup介绍
gitlab备份及迁移
Gitlab 创建备份 使用Gitlab一键安装包安装Gitlab非常简单, 同样的备份恢复与迁移也非常简单. 使用一条命令即可创建完整的Gitlab备份: gitlab-rake gitlab:backup:create 使用以上命令会在/var/opt/gitlab/backups目录下创建一个名称类似为1393513186_gitlab_backup.tar的压缩包, 这个压缩包就是Gitlab整个的完整部分, 其中开头的1393513186是备份创建的日期. Gitlab 修改备份文件默认目录 你也
程序员同行者
2018/06/22
9860
gitlab备份与恢复
gitlab-rake gitlab:backup:create  #执行命令备份数据库
似水的流年
2019/12/07
1.7K0
MySQL 数据备份与还原
步骤: 一.MYSQL的命令行模式的设置: 桌面->我的电脑->属性->环境变量->新建->PATH=";path/mysql/bin;"  其中path为MYSQL的安装路径。 二.命令行进入MYSQL的方法: 1.C:\>mysql -h hostname -u username -p 按ENTER键,等待然后输入密码,这里hostname为服务器的名称,如localhost,username为MYSQL的用户名,如root.进入命令行就可以直接操作MYSQL了。 三.从数据库导出数据库文件
昨天50还没用完
2018/06/29
2.1K0
mysql备份还原方案xtrabackup
摘要:mysql当数据库过大的时候,使用mysqldump的方式进行备份是一种非常慢的操作,500G的数据就够你备份一天一夜,我发现了一种mysql快速备份的方案,它使用文件存储的方式进行备份,支持全量和增量备份,这里所写为全量方式(如果可以接受备份开始到下次恢复之间的数据丢失时使用)。xtrabackup的备份速度很快,不管有多少的数据,备份速度完全是依赖于磁盘的读写速度,还支持压缩、不打断正在执行的事务、自动实现备份检验(用mysqldump会锁表,要加上可重复读--single-transaction才不会影响线上的程序写表,但是写表后的东西在还原的时候就会丢了,这也是全量备份的痛点)
机智的程序员小熊
2019/01/16
1.5K0
mysql备份还原方案xtrabackup
MySQL 数据备份与还原
mysqldump命令将数据库中的数据备份成一个文本文件,表的结构和表中的数据将存储在生成的文本文件中。
阮键
2020/04/30
2.3K0
MySQL 数据备份与还原
mongodb 备份、还原、导出、导入
mongodb数据备份和还原主要分为二种,一种是针对于库的mongodump和mongorestore,一种是针对库中表的mongoexport和mongoimport。
飞奔去旅行
2019/06/13
6.4K0
数据库备份/还原
开发的日常工作难免会遇到需要备份数据的场景,例如,DB特性变更,为了能备份便于回滚,亦或是,需要从不同服务器导数据。本文记录mysql、mongo数据库的常用导入/导出操作,方便查阅。
liliane
2022/08/14
4.7K0
mysql备份后缀是什么_mysql备份还原
格式:mysqldump -h主机名 -P端口 -u用户名 -p密码 –database 数据库名 > 文件名.sql
全栈程序员站长
2022/07/02
5.4K0
Mysql备份与还原——xtrabackup
上次我们介绍了采用逻辑备份mysqldump 备份方式,其最大的缺陷就是备份和恢复速度都慢,但如果数据库非常大,那再使用 mysqldump 备份就不太适合了。这时就需要一种好用又高效的工具,xtrabackup 就是其中一款,号称免费版的 InnoDB HotBackup。(mysqldump备份请到L宝宝聊IT公众号中找“mysql备份与还原——mysqldump结合binlog”文章)
L宝宝聊IT
2018/09/29
5.3K0
Mysql备份与还原——xtrabackup

相似问题

从Windows (.bat)脚本返回带有Unix行尾的回波文本

316

Windows cmd上的行尾

21

带有行尾字符的PHP

24

带有WIN32_LEAN_AND_MEAN的Windows头文件<Windows.h>

20

处理Python中的Windows行尾

42
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档