简体   繁体   中英

How can i pass the address of a buffer in user space to kernel

I want to use copy_to_user() to copy some information of a platform net device to a buffer in user space.But i don't how can kernel knows the "to" pointer which used by copy_to_user(). The driver's ioctl() needs struct ifreq as a parameter.And i know i can initialize the ifreq.name to find the driver's ioctl().But how can i pass the "to" pointer to kernel exactly the driver'ioctl()?

struct ifreq looks like this:

struct ifreq {
    char    ifr_name[IFNAMSIZ];/* Interface name */
    union {
            struct sockaddrifr_addr;
            struct sockaddrifr_dstaddr;
            struct sockaddrifr_broadaddr;
            struct sockaddrifr_netmask;
            struct sockaddrifr_hwaddr;
            short   ifr_flags;
            int     ifr_ifindex;
            int     ifr_metric;
            int     ifr_mtu;
            struct ifmapifr_map;
            char    ifr_slave[IFNAMSIZ];
            char    ifr_newname[IFNAMSIZ];
            char *  ifr_data;
    };
};

If you are implementing an existing ioctl command, you must figure out which of the members in the union you're supposed to use, both in user space and the kernel.

If you're implementing your own ioctl command, you can use ifr_data . The caller (in user space) sets the member to point to a local buffer, which you'd fill in with copy_to_user() in the kernel (ie ifr_data is the to that you're looking for.)

ie user space does

char buf[128];
struct ifreq req;
strcpy(req.ifr_name,"eth0");
req.ifr_data = buf;
ioctl(fd, SIOCMYIOCTL, &ifr);

Here the buffer is just a fixed size array, if you need more flexibility you can ofcourse use a struct, as long as user space and your kernel ioctl() agrees on what ifr_data is.

struct my_ioctl_data {
     int a, b, c;
};
struct my_ioctl_data data;
struct ifreq req;
strcpy(req.ifr_name,"eth0");
req.ifr_data = (char*)&data;
ioctl(fd, SIOCMYIOCTL, &ifr);

In the platform net device driver change the read method :

static ssize_t net_device_read(arg1,char __user *user_buffer,size_t count,loff_t *position)

{


   copy_to_user(user_buffer, position,count) != 0 

}

Access this buffer from the user space using cat command

 cat /dev/net-device 
>> string to pass

read more about this here : http://www.codeproject.com/Articles/112474/A-Simple-Driver-for-Linux-OS

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM