Linux kernel模块(.ko)实现unix domain socket通信(server)

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值