Как сделать схему связи в драйвере режима ядра Linux и в пользовательском режиме?

Я новичок в этой разработке драйверов Linux. Это моя первая программа, которая делает драйвер ядра. Я пытаюсь написать драйвер режима ядра и приложение пользовательского режима для чтения / записи этой зарезервированной области ядра. Я получил ошибку сегментации. Кто-нибудь может мне помочь?

Дело в том, что структура открытой функции ядра:

static int open(struct inode *inode, struct file *filp)
{
    struct mmap_info *info;
    char *data;

    pr_info("open\n");
    info = kmalloc(sizeof(struct mmap_info), GFP_KERNEL);

    // allocating memory on the heap for the data 
        data = kcalloc(MY_MMAP_LEN, sizeof(char), GFP_KERNEL);
        if (data == NULL)
        {
                printk(KERN_ERR "insufficient memory\n");
                /* insufficient memory: you must handle this error! */
                return ENOMEM;
        }

    info->data = data;

        printk(KERN_INFO "  > ->data:          0x%16p\n", info->data);
        memcpy(info->data, "Initial entry on mapped memory by the kernel module", 52);
        memcpy((info->data) + 0xf00, "Somewhere", 9);
        memcpy((info->data) + 0xf000, "Somehow", 7);
        printk(KERN_INFO "  > ->data: %c%c%c\n", // the output here is correct
            *(info->data + 0xf000 + 0), *(info->data + 0xf000 + 1), *(info->data + 0xf000 + 2));


    filp->private_data = info;
    return 0;
}

Но приложение пользовательского режима не имеет структуры данных filp->private_data->data. Как открыть с помощью правого указателя в приложении пользовательского режима. Вот часть кода открытия файла в приложении пользовательского режима:

     fd = open("/dev/ace", O_RDWR);
  if(fd < 0)
  {
    perror("Open call failed");
    return -1;
  }

  address = mmap( NULL,
                  MY_MMAP_LEN,
                  PROT_READ|PROT_WRITE,
                  MAP_SHARED,
                  fd,
                  0);
  if (address == MAP_FAILED)
  {
    perror("mmap operation failed");
    return -1;
  }

  sbuff = "This is a ACE demo\n";

  //memcpy(address, sbuff, 80);
  //usleep(5000);
  memcpy(sbuff, address,80);

Вся программа выглядит следующим образом: Исходный код режима ядра:

#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h> /* min */
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h> /* copy_from_user, copy_to_user */
#include <linux/slab.h>
#include <linux/device.h>

#define DEV_MODULENAME "ace"
#define DEV_CLASSNAME "aceclass"
static int majorNumber;
static struct class *devClass = NULL;
static struct device *devDevice = NULL;

enum { BUFFER_SIZE = 4 };

struct mmap_info {
    char *data;
};

/* After unmap. */
static void vm_close(struct vm_area_struct *vma)
{
    pr_info("vm_close\n");
}

/* First page access. */
    int (*fault)(struct vm_fault *vmf);
static int vm_fault(struct vm_fault *vmf)
{
    struct page *page;
    struct mmap_info *info;

    pr_info("vm_fault\n");
    info = (struct mmap_info *)vmf->vma->vm_private_data;
    if (info->data) {
            page = virt_to_page(info->data);
            get_page(page);
            vmf->page = page;
    }
    return 0;
}

/* Aftr mmap. TODO vs mmap, when can this happen at a different time than mmap? */
static void vm_open(struct vm_area_struct *vma)
{
    pr_info("vm_open\n");
}

static struct vm_operations_struct vm_ops =
{
    .close = vm_close,
    .fault = vm_fault,
    .open = vm_open,
};

static int mmap(struct file *filp, struct vm_area_struct *vma)
{
    pr_info("mmap\n");
    vma->vm_ops = &vm_ops;
    vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
    vma->vm_private_data = filp->private_data;
    vm_open(vma);
    return 0;
}

#define MY_MMAP_LEN 0x10000
static int open(struct inode *inode, struct file *filp)
{
    struct mmap_info *info;
    char *data;

    pr_info("open\n");
    info = kmalloc(sizeof(struct mmap_info), GFP_KERNEL);

    // allocating memory on the heap for the data 
        data = kcalloc(MY_MMAP_LEN, sizeof(char), GFP_KERNEL);
        if (data == NULL)
        {
                printk(KERN_ERR "insufficient memory\n");
                /* insufficient memory: you must handle this error! */
                return ENOMEM;
        }

    info->data = data;

        printk(KERN_INFO "  > ->data:          0x%16p\n", info->data);
        memcpy(info->data, "Initial entry on mapped memory by the kernel module", 52);
        memcpy((info->data) + 0xf00, "Somewhere", 9);
        memcpy((info->data) + 0xf000, "Somehow", 7);
        printk(KERN_INFO "  > ->data: %c%c%c\n", // the output here is correct
            *(info->data + 0xf000 + 0), *(info->data + 0xf000 + 1), *(info->data + 0xf000 + 2));


    filp->private_data = info;
    return 0;
}

static ssize_t read(struct file *filp, char __user *buf, size_t len, loff_t *off)
{
    struct mmap_info *info;
        int ret;

    pr_info("read\n");
    info = filp->private_data;
        ret = min(len, (size_t)BUFFER_SIZE);
        if (copy_to_user(buf, info->data, ret)) {
            ret = -EFAULT;
    }
    return ret;
}

static ssize_t write(struct file *filp, const char __user *buf, size_t len, loff_t *off)
{
    struct mmap_info *info;

    pr_info("write\n");
    info = filp->private_data;
        if (copy_from_user(info->data, buf, min(len, (size_t)BUFFER_SIZE))) {
            return -EFAULT;
        } else {
            return len;
        }
}

static int release(struct inode *inode, struct file *filp)
{
    struct mmap_info *info;

    pr_info("release\n");
    info = filp->private_data;
    free_page((unsigned long)info->data);
    kfree(info);
    filp->private_data = NULL;
    return 0;
}

static const struct file_operations fops = {
    .mmap = mmap,
    .open = open,
    .release = release,
    .read = read,
    .write = write,
};

static int __init
_module_init (void)
{
        int ret = 0;

        // Try to dynamically allocate a major number for the device
        majorNumber = register_chrdev(0, DEV_MODULENAME, &fops);
        if (majorNumber < 0)
        {
                printk(KERN_ALERT "Failed to register a major number.\n");
                return -EIO; // I/O error
        }

        // Register the device class
        devClass = class_create(THIS_MODULE, DEV_CLASSNAME);
        // Check for error and clean up if there is
        if (IS_ERR(devClass))
        {
                printk(KERN_ALERT "Failed to register device class.\n");
                ret = PTR_ERR(devClass);
                goto goto_unregister_chrdev;
        }

        // Create and register the device
        devDevice = device_create(devClass,
        NULL, MKDEV(majorNumber, 0),
        NULL,
        DEV_MODULENAME);

        // Clean up if there is an error
        if (IS_ERR(devDevice))
        {
                printk(KERN_ALERT "Failed to create the device.\n");
                ret = PTR_ERR(devDevice);
                goto goto_class_destroy;
        }
        printk(KERN_INFO "Module registered.\n");

        return ret;

        // Error handling - using goto
        goto_class_destroy: class_destroy(devClass);
        goto_unregister_chrdev: unregister_chrdev(majorNumber, DEV_MODULENAME);

        return ret;
}

static void __exit
_module_exit(void)
{
  device_destroy(devClass, MKDEV(majorNumber, 0));
  class_unregister(devClass);
  class_destroy(devClass);
  unregister_chrdev(majorNumber, DEV_MODULENAME);
  printk(KERN_INFO "Module unregistered.\n");
}

module_init(_module_init);
module_exit(_module_exit);

MODULE_LICENSE("GPL");

и вот приложение пользовательского режима:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <time.h>
#include <stdint.h>

#define MY_MMAP_LEN (0x10000)
#define PAGE_SIZE 4096

static char *exec_name;

int main ( int argc, char **argv )
{
  int fd;
  void *address = NULL;
  time_t t = time(NULL);
  char *sbuff;
  int i;

  exec_name = argv[0];
  sbuff = (char*) calloc(MY_MMAP_LEN,sizeof(char));

  fd = open("/dev/ace", O_RDWR);
  if(fd < 0)
  {
    perror("Open call failed");
    return -1;
  }

  address = mmap( NULL,
                  MY_MMAP_LEN,
                  PROT_READ|PROT_WRITE,
                  MAP_SHARED,
                  fd,
                  0);
  if (address == MAP_FAILED)
  {
    perror("mmap operation failed");
    return -1;
  }

  sbuff = "This is a ACE demo\n";

  //memcpy(address, sbuff, 80);
  //usleep(5000);
  memcpy(sbuff, address,80);
  printf("Initial message: %s\n", sbuff);
  //memcpy(sbuff, address+0xf00,80);
  //printf("Initial message: %s\n", sbuff);
  //memcpy(sbuff, address+0xf000,80);
  //printf("Initial message: %s\n", sbuff);

  usleep(5000);

  if (munmap(address, MY_MMAP_LEN) == -1)
  {
          perror("Error un-mmapping the file");
  }

  close(fd);

  return 0;
}

0 ответов

Другие вопросы по тегам