Linux kernel模块(.ko)实现unix domain socket通信(server)
ko server代码:
srv.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/un.h>
#include <net/sock.h>
#define SOCK_PATH "/dev/axlog"
#define LISTEN 10
static int __init server_module_init( void ) {
struct socket *sock = NULL;
struct socket *client_sock = NULL;
int retval;
struct sockaddr_un addr;
char *recvbuf=NULL;
struct kvec vec;
struct msghdr msg;
/*create*/
retval = sock_create(AF_UNIX, SOCK_STREAM, 0, &sock);
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, SOCK_PATH);
/*bind*/
retval = sock->ops->bind(sock,(struct sockaddr *)&addr, sizeof(addr));
if(retval<0){
printk("server: bind error\n");
return retval;
}
printk("server:bind ok!\n");
/*listen*/
retval = sock->ops->listen(sock, LISTEN);
if(retval<0){
printk("server: listen error\n");
return retval;
}
printk("server:listen ok!\n");
/*kmalloc a receive buffer*/
recvbuf=kmalloc(1025,GFP_KERNEL);
if(recvbuf==NULL){
printk("server: recvbuf kmalloc error!\n");
return -1;
}
while(1) {
printk("Accepting connections ...\n");
retval=kernel_accept(sock,&client_sock,10);
if(retval<0){
printk("server:accept error!\n");
continue;
}
printk("server: accept ok, Connection Established\n");
while(1) {
memset(recvbuf, 0, 1025);
/*receive message from client*/
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);
retval=kernel_recvmsg(client_sock,&msg,&vec,1,1024, msg.msg_flags); /*receive message*/
if (retval <= 0){
printk("receive message failed:\n %d\n",retval);
break;
}
printk("receive message: %s\n",recvbuf);
}
/*release socket*/
printk("release socket now\n");
sock_release(client_sock);
}
sock_release(sock);
return 0;
}
static void __exit server_module_exit( void ) {
printk(KERN_INFO "Exit usocket.");
}
module_init( server_module_init );
module_exit( server_module_exit );
MODULE_LICENSE("GPL");
【注意】
accept一定要使用kernel_accept,而不能使用sock->ops->accept,否则会出现kernel panic(原因待分析)。
Makefile
obj-m:=srv.o
CURRENT_PATH:=$(shell pwd)
VERSION_NUM:=$(shell uname -r)
LINUX_PATH:=/usr/src/linux-headers-$(VERSION_NUM)
all :
make -C $(LINUX_PATH) M=$(CURRENT_PATH) modules
clean:
make -C $(LINUX_PATH) M=$(CURRENT_PATH) clean
client端代码:
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#define MAXLINE 128
char *server_path = "/dev/axlog";
int main() {
struct sockaddr_un cliun, serun;
int len;
char buf[MAXLINE] = {0};
int sockfd, n;
if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
perror("client socket error");
exit(1);
}
memset(&cliun, 0, sizeof(cliun));
cliun.sun_family = AF_UNIX;
len = offsetof(struct sockaddr_un, sun_path) + strlen(cliun.sun_path);
unlink(cliun.sun_path);
if (bind(sockfd, (struct sockaddr *)&cliun, len) < 0) {
perror("bind error");
exit(1);
}
memset(&serun, 0, sizeof(serun));
serun.sun_family = AF_UNIX;
strcpy(serun.sun_path, server_path);
len = offsetof(struct sockaddr_un, sun_path) + strlen(serun.sun_path);
if (connect(sockfd, (struct sockaddr *)&serun, len) < 0){
perror("connect error");
exit(1);
}
while(fgets(buf, MAXLINE, stdin) != NULL) {
buf[strlen(buf)-1]='\0';
printf("write:%s\n", buf);
write(sockfd, buf, strlen(buf));
}
close(sockfd);
return 0;
}
gcc -o cli cli.c
运行srv:
sudo insmod srv.ko
运行cli
sudo ./cli
964

被折叠的 条评论
为什么被折叠?



