[etherlab-dev] mmap process data to user-space

Thomas Bitsky Jr tbj at automateddesign.com
Tue Jul 16 19:03:00 CEST 2013


Hello,

I have the master up and running and can connect from a kernel module. I'm trying to mmap a customer struct in the kernel-space to the user-space to exchange process data. I've been trying for days, but can't get it to work.

Everything seems to go fine in kernel-space and the user-space program can open the mmap'd file, but the data is absolute garbage. I must not be allocating the memory properly or something else fundamentally wrong. I've spent days reading on the Internet, but I always get the same result. Can someone tell me what I'm doing wrong?

Thanks in advance,
Tom


    ////////////////////////////////////////////////////////////
    // Includes
    ////////////////////////////////////////////////////////////

    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/fs.h>
    #include <linux/debugfs.h>

    // for kfree, kmalloc
    #include <linux/slab.h>

    // for mmap
    #include <linux/mm.h>


    #include "CtsSharedData.h"
    #include "ProcessData.h"
    #include "globals.h"


    /////////////////////////////////////////////////////////////////
    // Private variables
    //////////////////////////////////////////////////////////////////

    //
    // Pointer to the file in debugfs RAM file system
   static struct dentry* _ocFile;



    //
    // keep track of how often the item is mapped
    //
    void
    mmap_open(struct vm_area_struct* vma)
    {
        CtsProcessData* info = (CtsProcessData*)vma->vm_private_data;
        info->reference += 1;
    }


    //
    // keep track of how often the item is mapped
    //
    void
    mmap_close(struct vm_area_struct* vma)
    {
        CtsProcessData* info = (CtsProcessData*)vma->vm_private_data;
                info->reference -= 1;
    }

    int
    mmap_fault(struct vm_area_struct* vma, struct vm_fault *vmf)
    {

        unsigned long offset = vmf->pgoff << PAGE_SHIFT;
                CtsProcessData* priv = (CtsProcessData*) vma->vm_private_data;
        struct page *page;
                page = virt_to_page(priv + offset);
        if (!page)
                        return VM_FAULT_SIGBUS;

                get_page(page);
        vmf->page = page;

                priv->reference = 98765;


        PRINTF(CTSMSG_INFO "Vma fault, virtual_address = %p,"
                " offset = %lu, page = %p\n", vmf->virtual_address, offset, page);

                return 0;

    }


    static struct vm_operations_struct mmap_vm_ops =
    {
                .open = mmap_open,
        .close = mmap_close,
        .fault = mmap_fault,
    };



    //
    // Initilize the vm_area_struct to point to the mmap functions specific to
    // our implementation.
    //
    int
    ocMapPdTable(struct file* filp, struct vm_area_struct* vma)
    {
        PRINTF(CTSMSG_INFO": BEGIN: ocMapPdTable \n");

        //
                // The operations table describes the specific methods
        // that can operate on this particular instance of the object.
                //
        vma->vm_ops = &mmap_vm_ops;

                vma->vm_flags |= VM_RESERVED;

        vma->vm_private_data = filp->private_data;
                mmap_open(vma);


        PRINTF(CTSMSG_INFO": END: ocMapPdTable \n");

                return 0;
    }


    //
    // Frees the shared data table.
    //
    int
    ocClosePdTable(struct inode* inode, struct file* filp)
    {
                CtsProcessData* info = filp->private_data;

                PRINTF(CTSMSG_INFO": BEGIN: ocClosePdTable \n");

                kfree(info);
                filp->private_data = NULL;

                PRINTF(CTSMSG_INFO": END: ocClosePdTable \n");
                return 0;
    }


    //
    // Allocate the shared memory
    //
    int
    ocOpenPdTable(struct inode* inode, struct file* filp)
    {

                CtsProcessData* info;
                // unsigned long virt_addr;

                PRINTF(CTSMSG_INFO": BEGIN ocOpenPdTable\n");




                //
                // Create the process data in the kernel's memory
                //
                info = kmalloc(sizeof(CtsProcessData), GFP_KERNEL);

                /* round it up to the page bondary */
                // kmalloc_area = (int *)((((unsigned long)kmalloc_ptr) + PAGE_SIZE - 1) & PAGE_MASK);


                //
                // initialize the process data instance
                //
                memset(info, 0, sizeof(CtsProcessData));

                info->rawData = (CtsRawData*)kmalloc(sizeof(CtsRawData) * 1000, GFP_KERNEL);
                if (info->rawData == NULL)
                {
                                PRINTF("Failed to allocate memory for raw data!");
                }
                else
                {
                                memset(info->rawData, 0, (sizeof(CtsRawData) * 1000));


                                //
                                // FOR TESTING ONLY! Delete!

                                FPSET_16_16(info->rawData[0].load, 12, 0);
                                FPSET_16_16(info->rawData[0].position, 99, 0);
                                info->rawData[0].ticks = 54321;

                }


                filp->private_data = info;

                PRINTF(CTSMSG_INFO": END ocOpenPdTable\n");
                return 0;
    }


    static const struct file_operations oc_fops =
    {
                .open = ocOpenPdTable,
                .release = ocClosePdTable,
                .mmap = ocMapPdTable,
    };





    //////////////////////////////////////////////////
    // PUBLIC INTERFACE FUNCTIONS
    //////////////////////////////////////////////////


    //
    // Create the file in the debugfs RAM file system, which will trigger
    // mapping the memory
    //
    int
    ctsSharedTableCreate(void)
    {
                BOOL ret = FALSE;

                PRINTF(CTSMSG_INFO": BEGIN ocSharedTableCreate\n");


                _ocFile = debugfs_create_file(
                                CTSRT_DEBUGFS_SHAREDTABLE, // a pointer to a string containing the name of
                                                                                                                                                                                                                                                // the file to create.
                                0644, // the permission that the file should have
                                NULL, // a pointer to the parent entry for this file.
                                                                                // This should be a directory dentry if set.
                                                                                // If this paramater is NULL, then the file will be created in the
                                                                                // root of the debugfs filesystem.
                                NULL, // a pointer to something that the caller will want to get to later
                                                                                // on. The inode.i_private pointer will point to this
                                                                                // value on the open call.
                                &oc_fops);  // a pointer to a struct file_operations that should be used
                                                                                                                                // for this file.

                if (_ocFile == NULL)
                {
                                //
                                // Most likely, the kernel module crashed on exit and the file already
                                // exists. We don't have any way of deletlying it. The computer will
                                // need to be restarted.
                                //
                                PRINTF(CTSMSG_INFO": ctsSharedTableCreate failed to create debugfs file!\n");
                }
                else if ((int)_ocFile == -ENODEV)
                {
                                PRINTF(CTSMSG_INFO": ctsSharedTableCreate failed because of ENODEV!\n");
                }
                else
                {
                                PRINTF(CTSMSG_INFO": ctsSharedTableCreate succeeded.\n");
                                ret = TRUE;
                }

                return ret;
    }



    //
    // Close and delete the shared table and all associated memory.
    //
    void
    ctsSharedTableClose(void)
    {
                debugfs_remove(_ocFile);
    }




Thomas C. Bitsky Jr. | Lead Developer
ADC | automateddesign.com<http://automateddesign.com/>
P: 630-783-1150 F: 630-783-1159 M: 630-632-6679

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.etherlab.org/pipermail/etherlab-dev/attachments/20130716/97d75b6e/attachment-0001.htm>


More information about the etherlab-dev mailing list