内核态socket编程

代码位置:

EXPORT_SYMBOL(sock_create_kern);
EXPORT_SYMBOL(sock_release);
EXPORT_SYMBOL(kernel_bind);    
EXPORT_SYMBOL(kernel_listen);    
EXPORT_SYMBOL(kernel_accept);    
EXPORT_SYMBOL(kernel_connect); 
EXPORT_SYMBOL(kernel_sendmsg);    
EXPORT_SYMBOL(kernel_recvmsg);

net/socket.c

环境:ubuntu 20.04
server:

makefile:

# SPDX-License-Identifier: GPL-2.0
obj-m += rdma_rxe.o

rdma_rxe-objs := \
	socket.o
all:
	make -C /usr/src/linux-headers-$(shell uname -r) M=$(shell pwd) modules
clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean

server.c

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kthread.h>
#include <net/sock.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/netdevice.h>
#include <linux/if.h>
#include <linux/if_vlan.h>
#include <net/udp_tunnel.h>
#include <net/sch_generic.h>
#include <linux/netfilter.h>
static struct task_struct *task;    //内核线程任务头

//内核线程服务函数,重点!!!!
static int socket_threadfn(void *data)
{
    struct socket *sock, *nsock;
    struct sockaddr_in addr;
    int err;
    
    //建立套接字
    err = sock_create_kern(&init_net, PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
    if(err < 0)
    {
        printk("sock_create_kern failed.\n");
        return -1;
    }
    
    //绑定端口
    memset(&addr, '\0', sizeof(addr));    
    addr.sin_family      = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port        = htons(8888);
    err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr));
    if (err < 0)
    {
        printk("kernel_bind failed.\n");
        sock_release(sock);
        return -1;
    }
    
    //监听端口
    err = kernel_listen(sock, 1024);
    if (err < 0)
    {
        printk("kernel_listen failed.\n");
        sock_release(sock);
        return -1;
    }
    
    //等待连接
    err = kernel_accept(sock, &nsock, 0);
    if (err < 0)
    {
        printk("kernel_accept failed.\n");
        sock_release(sock);
        return -1;
    }
    
    //任务主循环
    while (!kthread_should_stop()) 
    {
        struct msghdr       msg = {NULL,};
        struct kvec         iov;
        char buffer[1024];
        int len, buflen = sizeof(buffer);
        
        iov.iov_base     = buffer;
        iov.iov_len      = (size_t)buflen;
        
        //等待sk_bufer中数据可读       
        wait_event_interruptible(*sk_sleep(nsock->sk),
              !skb_queue_empty(&nsock->sk->sk_receive_queue) || kthread_should_stop());
              
        if(!skb_queue_empty(&nsock->sk->sk_receive_queue))
        {
            len = kernel_recvmsg(nsock, &msg, &iov, 1, buflen, MSG_DONTWAIT);
            if(len<0)
                printk("receiving message error\n");
            else
                printk("receiving: %s\n", buffer);
        }
    }
    sock_release(nsock);
    sock_release(sock);
    return 0;
}

int __init test_server_init(void)
{
    task = kthread_run(socket_threadfn, NULL, "listen thread");
    return 0;
}

void __exit test_server_exit(void)
{
}
module_init(test_server_init);
module_exit(test_server_exit);
MODULE_LICENSE("GPL");

make以后插入ko,

client:

client.c

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc, char* argv[])
{
	struct sockaddr_in serverAddr;
	char buffer[1024];
	int sock, retl;
	
	sock = socket(PF_INET,SOCK_STREAM , 0);
	assert(sock >= 0);
	
	bzero(&serverAddr,sizeof(serverAddr));

	serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serverAddr.sin_port = htons(8888);
    serverAddr.sin_family = AF_INET;
	retl = connect(sock, (const struct sockaddr *)&serverAddr, (socklen_t)sizeof(struct sockaddr));
	assert(retl >= 0);
	
	retl=0;
	while(1)
	{
		retl++;
		sprintf(buffer, "This is frame number %d", retl);
		send(sock, buffer, strlen(buffer), 0);
		sleep(1);
	}
	
	return 0;
}

gcc编译后运行 ./client

dmesg:
在这里插入图片描述
参考:https://blog.csdn.net/fengsapiao/article/details/124706203

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值