代码位置:
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