Re: Accessing a Struct in Kernel Memory from User Space via ioctl

Zachary Amsden (amsdenz@aavid.com)
Tue, 21 Jul 1998 09:07:45 -0400


-----Original Message-----
From: chris@symsystems.com <chris@symsystems.com>
To: Linux Kernel Programming <linux-kernel@vger.rutgers.edu>
Date: Monday, July 20, 1998 6:26 PM
Subject: Accessing a Struct in Kernel Memory from User Space via ioctl

>I have a module that gets data from a PCI device and stores in into a
>struct in kernel space. How would I go about accessing the information
>contained in the struct via an ioctl call in user space? Or am I going
>about this this wrong way? :-)
>
>Thanks,
>Chris

Warning: lengthy. I hope this helps, can not guarantee 100% accuracy, I've never written a driver before.

I assume you want to get some static data from the device, i.e. firmware version or something. Create a /dev entry that you can ioctl() on, with appropriate major/minor numbers. It doesn't really matter whether you use a block/char device, I would suggest a block device because then you could optionally allow a read on /dev/mypci to get the data. You will need an init func similar to like

static struct file_operations pci_fops = {
/* function references */
};

__initfunc(int foo_init(void))
{
if (register_blkdev(MAJOR_NR,"pci", &pci_fops))
/* Error, bomb out */
/* Initialize any data */
}

register_blkdev will direct all calls to devices with MAJOR_NR to the supplied file operations structure, pci_fops. The fops structure contains a whole bunch of pointers to functions: lseek, read, write, readdir, poll, ioctl, mmap, open, release, fsync.

Your ioctl function will be something like: (checking for sysadmin capability is probably optional depending on your type of device and data).

static int pci_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int dev;

if ((!inode) || (!inode->i_rdev))
return -EINVAL;
dev = DEVICE_NR(inode->i_rdev);
if (dev >= NR_DEVS)
return -EINVAL;
switch (cmd) {
case PCI_GETSTRUCT: {
struct pcistruct p;
if (!arg)
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EACCESS;
p.data = get_from_dev(dev);
if (copy_to_user((void *) arg, &p, sizeof(p)))
return -EFAULT;
else
return 0;
}
}
}

--
Zachary Amsden
Designer of Advanced Gamma Neutron Devices and Linux Kernel Hacker
amsden@andrew.cmu.edu

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.altern.org/andrebalsa/doc/lkml-faq.html