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
_______________________________________________ etherlab-dev mailing list etherlab-dev@etherlab.org http://lists.etherlab.org/mailman/listinfo/etherlab-dev