我尝试将一些数据从用户模式发送到我的内核模块。但是当它发送内容时,会触发内核错误:
错误:无法处理内核分页请求ad ffff88022f168bc0
IP:[< ...>] build_skb + 0xf5 / 0x1c0
#include "socket.hpp"
using namespace std;
KernelSocket::KernelSocket(DataLink * dl){
this->dl = dl;
this->sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
if(sock_fd<0) {
printf("unable to create socket%d\n", sock_fd);
exit(-1);
}
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid();
//src_addr.nl_groups = 0;
bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0;
dest_addr.nl_groups = 0;
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
memset(nlh,0,NLMSG_SPACE(MAX_PAYLOAD));
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
reportLocalAddress();
}
void KernelSocket::sendToKernel(string data){
int length = data.length();
char c;
c = (length%0xff);
data.insert(0, 1, c);
c = (length/0xff);
data.insert(0, 1, c);
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
memcpy((NLMSG_DATA(nlh)), data.c_str(), length+2);
iov.iov_base = (void *)nlh;
iov.iov_len = nlh->nlmsg_len;
//iov.iov_len = length;
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
sendmsg(sock_fd,&msg,0);
}
void KernelSocket::reportLocalAddress(){
int length = 6;
string data = dl->localAddress.toString();
data.insert(0,1, 0xff);
data.insert(0,1, 0xff);
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
memcpy((NLMSG_DATA(nlh)), data.c_str(), length+2);
iov.iov_base = (void *)nlh;
iov.iov_len = nlh->nlmsg_len;
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
sendmsg(sock_fd,&msg,0);
printf("send mac address to kernel\n");
}
void * kernelSocketWorkLoop(void * kernelSocket){
int length,ret;
KernelSocket * ks = (KernelSocket *) kernelSocket;
while(1){
ret = recvmsg(ks->sock_fd, &(ks->msg), MSG_DONTWAIT);
if(ret>=0){
string c;
c.assign((char *)NLMSG_DATA(ks->nlh));
length = c[0]*0xff+c[1];
ks->dl->packetDownBuffer.push(c);
}
sleep(1);
}
}
我现在正在使用此期间代码。有人对这个问题有意见吗?感谢〜
这是我用来接收消息的内核模块中的函数。
static void ss_recv(struct sk_buff *skb){
struct nlmsghdr *nlh;
int len;
char * c;
struct uwmodem_priv* priv = NULL;
priv = netdev_priv(dev);
printk("in ss_recv\n");
nlh = (struct nlmsghdr *)skb->data;
if(nlh->nlmsg_pid>0){
priv->daemon_pid = nlh->nlmsg_pid;
len = nlh->nlmsg_len - NLMSG_HDRLEN;
c = kmalloc(len, GFP_ATOMIC);
if(c==NULL){
printk("Fail to allocate c\n");
}
memcpy(c, nlmsg_data(nlh), len);
if(c[0]==0xff && c[1]==0xff){
printk("Set MacAddress(%d) \n", nlh->nlmsg_pid);
//for mac address
memcpy(dev->dev_addr, c+2, ETH_ALEN);
}else{
len = c[0]*0xff+c[1];
//printk("Kernel Length:[%d][%d][%d]\n", c[0], c[1], c[2]);
printk("Kernel received from (%d)[%d]: \n", nlh->nlmsg_pid,len);
uwmodem_rx(dev, c+2, len);
}
kfree(c);
}
//printk("Exit ss_recv\n");
}