我想在linux内核空间下实现一个TCP服务器。它可以接受新连接,但是,在调用kernel_recvmsg
接收数据时,内核会立即挂起。
#define BUFFSIZE 1024
int myserver(void)
{
struct socket *sock,*client_sock;
struct sockaddr_in s_addr;
unsigned short portnum=8888;
int ret=0;
memset(&s_addr,0,sizeof(s_addr));
s_addr.sin_family=AF_INET;
s_addr.sin_port=htons(portnum);
s_addr.sin_addr.s_addr=in_aton("192.168.0.70");
sock=(struct socket *)kmalloc(sizeof(struct socket),GFP_KERNEL);
client_sock=(struct socket *)kmalloc(sizeof(struct socket),GFP_KERNEL);
/*create a socket*/
ret=sock_create_kern(&init_net, AF_INET,SOCK_STREAM, IPPROTO_TCP,&sock);
/*bind the socket*/
ret=sock->ops->bind(sock,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
if(ret<0){
printk("server: bind error\n");
return ret;
}
printk("server:bind ok!\n");
/*listen*/
ret=sock->ops->listen(sock,10);
if(ret<0){
printk("server: listen error\n");
return ret;
}
printk("server:listen ok!\n");
ret=sock->ops->accept(sock,client_sock,10);
if(ret<0){
printk("server:accept error!\n");
return ret;
}
printk("server: accept ok, Connection Established\n");
/*kmalloc a receive buffer*/
char *recvbuf=NULL;
recvbuf=kmalloc(1024,GFP_KERNEL);
if(recvbuf==NULL){
printk("server: recvbuf kmalloc error!\n");
return -1;
}
memset(recvbuf, 0, sizeof(recvbuf));
/*receive message from client*/
struct kvec vec;
struct msghdr msg;
memset(&vec,0,sizeof(vec));
memset(&msg,0,sizeof(msg));
vec.iov_base=recvbuf;
vec.iov_len=1024;
msg.msg_flags=MSG_NOSIGNAL;
msleep(1000);
/*hi, kernel hangs here!*/ ret=kernel_recvmsg(client_sock,&msg,&vec,1,1024, msg.msg_flags);
recvbuf[1023] = 0;
printk("receive message:\n %s\n",recvbuf);
/*release socket*/
printk("release socket now\n");
sock_release(client_sock);
sock_release(sock);
return ret;
}
static int server_init(void){
printk("server init:\n");
return (myserver());
}
以上是代码。以下句子挂起。我的内核版本是3.2.1
。我使用kgdb来调试内核,gdb显示received signal SIGSEGV, Segmentation fault
。
ret=kernel_recvmsg(client_sock,&msg,&vec,1,1024, msg.msg_flags);
答案 0 :(得分:0)
我应该使用kernel_accept
代替sock->ops->accept
,因为kernel_accept
会更多地初始化sock->ops
ret=kernel_accept(sock,&client_sock,10);