内核态的socket编程
来源:互联网 发布:360mac版 dmg 编辑:程序博客网 时间:2024/06/11 19:03
记不清从哪个kernel版本开始,内核态就不能直接使用系统调用了。当然,socket的系统调用也不能用了。不过好在kernel提供了一组内核态的socket API。在net/socket.c文件中,可以看到这么几个导出符号:
EXPORT_SYMBOL(kernel_sendmsg);EXPORT_SYMBOL(kernel_recvmsg);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_getsockname);EXPORT_SYMBOL(kernel_getpeername);EXPORT_SYMBOL(kernel_getsockopt);EXPORT_SYMBOL(kernel_setsockopt);EXPORT_SYMBOL(kernel_sendpage);EXPORT_SYMBOL(kernel_sock_ioctl);EXPORT_SYMBOL(kernel_sock_shutdown);
基本上,在用户态的socket的API,在内核态都有对应的API。
下面是一个项目中的代码,socket操作我加了注视。不用去关心代码功能,只要看一下socket部分的操作即可,非常简单。
#include <linux/socket.h>#include <linux/net.h>#include <linux/in.h>struct fsg_common{.... struct socket *encrypt_sock; struct msghdr encrypt_msg; struct sockaddr_in encrypt_servaddr; struct data_pkt *encrypt_pkt;}static int encrypt_socket_init(struct fsg_common *common){struct socket *sock;int ret;char *dst_addr = "111.111.111.111";/* init servaddr */memset(&common->encrypt_servaddr, 0, sizeof(common->encrypt_servaddr));common->encrypt_servaddr.sin_family = AF_INET;common->encrypt_servaddr.sin_port = htons(9999);//kernel态的IP地址转换函数,有两个函数in4_pton和in6_pton,分别用于IPv4和IPv6in4_pton(dst_addr, strlen(dst_addr), (u8*)&common->encrypt_servaddr.sin_addr, '\0', NULL);//内核态udp通信地址使用struct msghdr封装common->encrypt_msg.msg_name = &common->encrypt_servaddr;common->encrypt_msg.msg_namelen = sizeof(common->encrypt_servaddr);//创建套接字,类似socket()函数,返回的sock指针就是后面数据传递用的套接字了ret = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);if (ret < 0 || NULL == sock) {ERROR(common, "init encrypt board socket fail\n");return ret;}common->encrypt_sock = sock;common->encrypt_pkt = kmalloc(sizeof(struct data_pkt), GFP_KERNEL);if (NULL == common->encrypt_pkt)return -1;return 0;}static void encrypt_socket_close(struct fsg_common *common){//关闭套接字,类似用户态的close()函数sock_release(common->encrypt_sock);common->encrypt_sock = NULL;}static int encrypt_data(struct fsg_common *common, u8* data, unsigned int size, loff_t offset){struct socket *sock = common->encrypt_sock; struct data_pkt *pkt = common->encrypt_pkt;struct sockaddr *pservaddr = (struct sockaddr *)&common->encrypt_servaddr;int servlen = sizeof(common->encrypt_servaddr);if (unlikely(NULL == sock || NULL == pkt || NULL == pservaddr))return -1;memset(pkt, 0, sizeof(struct data_pkt));unsigned int copied_size = 0;struct kvec vec;struct msghdr msg;memset(&msg, 0, sizeof(msg));while (copied_size < size) {pkt->res=0xffffffff;pkt->file_offset = offset; memcpy(pkt->data, data + copied_size, SECTOR_SIZE);//配置udp发送数据地址及长度vec.iov_base = (void *)pkt;vec.iov_len = sizeof(struct data_pkt);ret = kernel_sendmsg(sock, &common->encrypt_msg, &vec, 1, sizeof(struct data_pkt));printk("send data(return :%d):\n", ret);//接收udp报文ret = kernel_recvmsg(sock, &msg, &vec, 1, sizeof(struct data_pkt), 0);printk("recv data(return :%d):\n", ret);memcpy(data+copied_size, pkt->data, 512);copied_size += 512;} return 0;}可以看出来,kernel态的udp通信除了具体API及参数不同,过程和用户态是完全一样的。
- 内核态的socket编程
- 内核态socket编程
- Linux 内核态 Socket 编程
- Linux 内核态 Socket 编程
- 内核态 Socket TCP编程
- 内核态 Socket UDP编程
- Linux 内核态 Socket TCP 编程
- Linux 内核态 Socket 编程--更正
- Linux内核开发五:Socket网络编程
- Linux内核协议栈(2) 由简单的socket编程例子开始
- netlink socket 用户态和内核态的通信
- Socket编程的流程
- Delphi的Socket编程
- Linux的socket编程
- Socket的网络编程
- socket编程的注意事项
- Erlang 的Socket编程
- 简单的socket编程
- SqlBulkCopy(批量复制)使用方法
- 两个版本的二分查找
- 字符数组和字符指针应用举例
- Android 从驱动到应用层添加代码流程
- linux内核设计与实现(第五章)----系统调用
- 内核态的socket编程
- ubuntu 安装拼音
- Tomcat 服务无法启动 找不到指定的模块
- 中文分词资料
- excel 2007数据透视表教程
- 编译PHP遇到的错误处理,缺少的库及补全办法。
- 二叉树转双向链表
- Listener refused the connection with the following error 错误解
- android 实现代码关机