首页 > 解决方案 > 使用独立的 c++ 程序处理用 c 编写的字符设备驱动程序

问题描述

我正在开发一个基于 Linux 字符设备驱动程序的项目,并且我是实现设备驱动程序的新手。我使用了文件 file_operations 结构并在其上定义了我自己的函数,如下所述。

#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#define  DEVICE_NAME "char_Driver"
#define  CLASS_NAME  "chrDev"

MODULE_LICENSE("GPL");

static int    majorNumber;
static char   message[128] = {0};
static int    numberOpens = 0;
static struct class*  charClass  = NULL;
static struct device* charDevice = NULL;

static int     dev_open(struct inode *, struct file *);
static int     dev_release(struct inode *, struct file *);
static ssize_t dev_read(struct file *, char *, size_t, loff_t *);
static ssize_t dev_write(struct file *, const char *, size_t, loff_t *);

static struct file_operations fops =
{
    .owner = THIS_MODULE,
    .open = dev_open,
    .read = dev_read,
    .write = dev_write,
    .release = dev_release,
};

static int __init char_init(void){
   printk(KERN_INFO "Char_Driver: Initializing the CharDriver LKM\n");
   majorNumber = register_chrdev(0, DEVICE_NAME, &fops);
   printk(KERN_INFO "char_Driver: registered correctly with major number %d\n", majorNumber);
   charClass = class_create(THIS_MODULE, CLASS_NAME);
   charDevice = device_create(charClass, NULL, MKDEV(majorNumber, 0), NULL, DEVICE_NAME);
   return 0;
}

static void __exit char_exit(void){
   device_destroy(charClass, MKDEV(majorNumber, 0));
   class_unregister(charClass);
   class_destroy(charClass);
   unregister_chrdev(majorNumber, DEVICE_NAME);
   printk(KERN_INFO "Char_Driver: LKM Unloaded!\n");
}

static int dev_open(struct inode *inodep, struct file *filep){
   numberOpens++;
   printk(KERN_INFO "Char_Driver: Device has been opened %d times\n", numberOpens);
   return 0;
}

ssize_t dev_read(struct file *filep, char *buffer, size_t len, loff_t *offset){
    size_t ret = copy_to_user(buffer, message, len);
    printk(KERN_INFO "Char_Driver: Sent %zu characters to the user\n", len);
    return ret;
}

ssize_t dev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset){
    size_t ret = copy_from_user(message,buffer,len);
    printk(KERN_INFO "Char_Driver: Received %zu characters from the user\n", len);
    return ret;
}

static int dev_release(struct inode *inodep, struct file *filep){
   printk(KERN_INFO "Char_Driver: Device successfully closed\n");
   return 0;
}

module_init(char_init);
module_exit(char_exit);

当内核模块加载时,我会自动在 /dev 目录中创建一个名为“char_driver”的字符设备文件。

我的问题是当我使用 ac 程序从设备文件中写入和读取时,它工作得很好。但是当我使用以下 C++ 程序访问该设备驱动程序时,同样的事情会发生。内核无限地记录“Char_Driver:从用户那里收到 5 个字符”消息。

#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdio>

using namespace std;

static fstream dev_file;

#define BUFFER_LENGTH 128
static char receive[BUFFER_LENGTH];
int main(){
    int ret;
    char stringToSend[BUFFER_LENGTH];
    cout << "Starting device test code example...\n";
    dev_file.open("/dev/char_Driver", ios::out);
    if (!dev_file){
        cout << "Failed to open the device...\n";
        return -1;
    }
    cout << "Type in a short string to send to the kernel module:\n";
    cin >> stringToSend;
    cout << "Writing message to the device [" << stringToSend << "]\n";

    dev_file.write(stringToSend, strlen(stringToSend));
    dev_file.close();

    cout << "Press ENTER to read back from the device...\n";
    getchar();


    cout << "file closed successfully..\n";
    dev_file.open("/dev/char_Driver", ios::in);

    cout << "Reading from the device...\n";
    dev_file.read(receive, BUFFER_LENGTH);
    if (ret < 0){
        cout << "Failed to read the message from the device.\n";
        return -1;
    }
    printf("The received message is: [%s]\n", receive);
    printf("End of the program\n");
    dev_file.close();
    return 0;
}

下面提到了我对上述 c++ 程序的预期输出,它完美地适用于普通文件(*.txt、*.sh 等)。

Starting device test code example...
Type in a short string to send to the kernel module:
test
Writing message to the device [test]
Press ENTER to read back from the device...

file closed successfully..
Reading from the device...
The received message is: [test]
End of the program

但目前的输出是,

Starting device test code example...
Type in a short string to send to the kernel module:
test
Writing message to the device [test]

和无限的内核日志。还有一件事,当我使用时,

echo 'test' >> /dev/char_Driver "

命令还内核无限记录“Char_Driver:从用户那里收到 5 个字符”。您的帮助非常可观。

标签: c++clinux

解决方案


这个copy_from_user参考

返回无法复制的字节数。成功后,这将为零

[强调我的]

dev_write函数应返回它“接受”的字节数(或负错误代码),而不是零。

换句话说,它应该返回len而不是ret


推荐阅读