Linux kernel下的内核socket编程

内核4版本下测试通过,引用了高手的代码,做了修改,避免崩溃:

https://www.linuxquestions.org/questions/blog/915086731-521769/implementation-of-server-client-socket-under-kernel-environment-37716/

server:

#include<linux/in.h>  
#include<linux/inet.h>  
#include<linux/socket.h>  
#include<net/sock.h>  
  
#include<linux/init.h>  
#include<linux/module.h>  

#define BUFFSIZE 1024

void jiang_debug( void )
{
    printk("just debug");
}

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);  

    /*create a socket*/  
    ret=sock_create_kern(&init_net, AF_INET,SOCK_STREAM, IPPROTO_TCP,&sock);  
    if(ret){  
            printk("server:socket_create error!\n");  
    }  
    printk("server:socket_create ok!\n");  

    /*bind the socket*/  
    ret=kernel_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=kernel_listen(sock,10);  
    if(ret<0){  
            printk("server: listen error\n");  
            return ret;  
    }  
    printk("server:listen ok!\n");  

    ret=kernel_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, 1024);  

    /*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);
    jiang_debug();
    ret=kernel_recvmsg(client_sock,&msg,&vec,1,1024, msg.msg_flags); /*receive message*/  
    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());  
}  
  
static void server_exit(void){  
    printk("good bye\n");  
}  
  
module_init(server_init);  
module_exit(server_exit);  
  
MODULE_LICENSE("GPL");

client:

#include<linux/in.h>
#include<linux/inet.h>
#include<linux/socket.h>
#include<net/sock.h>
#include<linux/init.h>
#include<linux/module.h>
#define BUFFER_SIZE 1024
int connect_send_recv(void){
    struct socket *sock;
    struct sockaddr_in s_addr;
    unsigned short port_num = 8888;
    int ret = 0;
    char *send_buf = NULL;
    char *recv_buf = NULL;
    struct kvec send_vec, recv_vec;
    struct msghdr send_msg, recv_msg;
    /* kmalloc a send buffer*/
    send_buf = kmalloc(BUFFER_SIZE, GFP_KERNEL);
    if (send_buf == NULL) {
        printk("client: send_buf kmalloc error!\n");
        return -1;
    }
    /* kmalloc a receive buffer*/
    recv_buf = kmalloc(BUFFER_SIZE, GFP_KERNEL);
    if(recv_buf == NULL){
        printk("client: recv_buf kmalloc error!\n");
        return -1;
    }
    memset(&s_addr, 0, sizeof(s_addr));
    s_addr.sin_family = AF_INET;
    s_addr.sin_port = htons(port_num);
    s_addr.sin_addr.s_addr = in_aton("192.168.0.71");
    sock = (struct socket *)kmalloc(sizeof(struct socket), GFP_KERNEL);
    // 创建一个sock, &init_net是默认网络命名空间
    ret = sock_create_kern(&init_net, AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
    if (ret < 0) {
        printk("client:socket create error!\n");
        return ret;
    }
    printk("client: socket create ok!\n");
    //连接
    ret = sock->ops->connect(sock, (struct sockaddr *)&s_addr, sizeof(s_addr), 0);
    if (ret != 0) {
        printk("client: connect error!\n");
        return ret;
    }
    printk("client: connect ok!\n");
    memset(send_buf, 'a', BUFFER_SIZE);
    memset(&send_msg, 0, sizeof(send_msg));
    memset(&send_vec, 0, sizeof(send_vec));
    send_vec.iov_base = send_buf;
    send_vec.iov_len = BUFFER_SIZE;
    // 发送数据
    ret = kernel_sendmsg(sock, &send_msg, &send_vec, 1, BUFFER_SIZE);
    if (ret < 0) {
        printk("client: kernel_sendmsg error!\n");
        return ret;
    } else if(ret != BUFFER_SIZE){
        printk("client: ret!=BUFFER_SIZE");
    }
    printk("client: send ok!\n");
    memset(recv_buf, 0, BUFFER_SIZE);
    memset(&recv_vec, 0, sizeof(recv_vec));
    memset(&recv_msg, 0, sizeof(recv_msg));
    recv_vec.iov_base = recv_buf;
    recv_vec.iov_len = BUFFER_SIZE;
    // 接收数据
    ret = kernel_recvmsg(sock, &recv_msg, &recv_vec, 1, BUFFER_SIZE, 0);
    printk("client: received message:\n %s\n", recv_buf);
    // 关闭连接
    kernel_sock_shutdown(sock, SHUT_RDWR);
    sock_release(sock);
    return 0;
}
static int client_example_init(void){
    printk("client: init\n");
    return connect_send_recv();
}
static void client_example_exit(void){
    printk("client: exit!\n");
}
module_init(client_example_init);
module_exit(client_example_exit);
MODULE_LICENSE("GPL");


Please pay attentation, you must call kernel_accept instead of sock->ops->accept. Or you will get into kernel panic.


  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Linux默认内核是由Linus Torvalds开发的Linux内核。要进行内核配置,可以使用make menuconfig或make config命令进行交互式配置,也可以使用make defconfig命令使用默认配置。以下是更详细的步骤: 1. 下载Linux内核源代码,并解压缩。 2. 进入内核源代码目录,运行make menuconfig命令,进入交互式配置界面。 3. 在界面中,可以选择不同的内核配置选项。例如,选择“General setup”选项,可以配置内核的基本设置,如内核版本号、支持的处理器架构、系统时间等。 4. 选择“Processor type and features”选项,可以配置内核的处理器类型和特性,如是否支持超线程、是否支持SSE指令集等。 5. 选择“Networking support”选项,可以配置内核对网络的支持,如是否启用IPv6、是否支持网络设备驱动等。 6. 选择“File systems”选项,可以配置内核对文件系统的支持,如是否支持ext4、NTFS等。 7. 配置完成后,可以保存配置并退出。此时,内核配置文件会被保存为.config文件。 8. 运行make命令,编译内核。编译完成后,会生成一个内核镜像文件。 9. 将内核镜像文件拷贝到/boot目录下。 10. 配置引导程序,使其启动新的内核。具体步骤因引导程序而异,这里不再赘述。 以上是Linux内核配置的基本步骤。需要注意的是,配置内核时需要根据实际需求进行选择,不要选择过多或不必要的功能,以免浪费系统资源。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值