【发布时间】:2014-09-03 09:35:18
【问题描述】:
我想使用 copy_to_user() 将平台网络设备的一些信息复制到用户空间的缓冲区。但我不知道内核如何知道 copy_to_user() 使用的“to”指针。 驱动程序的 ioctl() 需要 struct ifreq 作为参数。而且我知道我可以初始化 ifreq.name 以找到驱动程序的 ioctl()。但是我怎样才能将“to”指针准确地传递给内核 driver'ioctl()?
【问题讨论】:
我想使用 copy_to_user() 将平台网络设备的一些信息复制到用户空间的缓冲区。但我不知道内核如何知道 copy_to_user() 使用的“to”指针。 驱动程序的 ioctl() 需要 struct ifreq 作为参数。而且我知道我可以初始化 ifreq.name 以找到驱动程序的 ioctl()。但是我怎样才能将“to”指针准确地传递给内核 driver'ioctl()?
【问题讨论】:
结构 ifreq 看起来像这样:
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;
};
};
如果您要实现现有的 ioctl 命令,则必须弄清楚您应该使用联合中的哪些成员,无论是在用户空间还是内核中。
如果您要实现自己的 ioctl 命令,则可以使用 ifr_data。调用者(在用户空间中)将成员设置为指向本地缓冲区,您将在内核中使用 copy_to_user() 填充该缓冲区(即 ifr_data 是您正在寻找的 to 。 )
即用户空间可以
char buf[128];
struct ifreq req;
strcpy(req.ifr_name,"eth0");
req.ifr_data = buf;
ioctl(fd, SIOCMYIOCTL, &ifr);
这里的缓冲区只是一个固定大小的数组,如果您需要更大的灵活性,您当然可以使用结构,只要用户空间和您的内核 ioctl() 同意 ifr_data 是什么。
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);
【讨论】:
在平台网络设备驱动中更改读取方法:
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
}
使用 cat 命令从用户空间访问这个缓冲区
cat /dev/net-device
>> string to pass
在此处阅读更多信息:http://www.codeproject.com/Articles/112474/A-Simple-Driver-for-Linux-OS
【讨论】: