内核态socket编程

来源:互联网 发布:好团队软件 编辑:程序博客网 时间:2024/05/19 22:04
 

内核态的socket编程

分类: 嵌入式开发 794人阅读 评论(0) 收藏 举报

记不清从哪个kernel版本开始,内核态就不能直接使用系统调用了。当然,socket的系统调用也不能用了。不过好在kernel提供了一组内核态的socket API。在net/socket.c文件中,可以看到这么几个导出符号:

[cpp] view plaincopyprint?
  1. EXPORT_SYMBOL(kernel_sendmsg);  
  2. EXPORT_SYMBOL(kernel_recvmsg);  
  3. EXPORT_SYMBOL(sock_create_kern);  
  4. EXPORT_SYMBOL(sock_release);  
  5. EXPORT_SYMBOL(kernel_bind);  
  6. EXPORT_SYMBOL(kernel_listen);  
  7. EXPORT_SYMBOL(kernel_accept);  
  8. EXPORT_SYMBOL(kernel_connect);  
  9. EXPORT_SYMBOL(kernel_getsockname);  
  10. EXPORT_SYMBOL(kernel_getpeername);  
  11. EXPORT_SYMBOL(kernel_getsockopt);  
  12. EXPORT_SYMBOL(kernel_setsockopt);  
  13. EXPORT_SYMBOL(kernel_sendpage);  
  14. EXPORT_SYMBOL(kernel_sock_ioctl);  
  15. EXPORT_SYMBOL(kernel_sock_shutdown);  

基本上,在用户态的socket的API,在内核态都有对应的API。


下面是一个项目中的代码,socket操作我加了注视。不用去关心代码功能,只要看一下socket部分的操作即可,非常简单。

[cpp] view plaincopyprint?
  1. #include <linux/socket.h>  
  2. #include <linux/net.h>  
  3. #include <linux/in.h>  
  4.   
  5. struct fsg_common{  
  6. ....  
  7.         struct socket *encrypt_sock;   
  8.         struct msghdr encrypt_msg;  
  9.         struct sockaddr_in encrypt_servaddr;  
  10.         struct data_pkt *encrypt_pkt;  
  11. }  
  12.   
  13. static int encrypt_socket_init(struct fsg_common *common)  
  14. {  
  15.     struct socket *sock;  
  16.     int ret;  
  17.     char *dst_addr = "111.111.111.111";  
  18.     /* init servaddr */  
  19.     memset(&common->encrypt_servaddr, 0, sizeof(common->encrypt_servaddr));  
  20.     common->encrypt_servaddr.sin_family = AF_INET;  
  21.     common->encrypt_servaddr.sin_port = htons(9999);  
  22.       
  23.     //kernel态的IP地址转换函数,有两个函数in4_pton和in6_pton,分别用于IPv4和IPv6  
  24.     in4_pton(dst_addr, strlen(dst_addr), (u8*)&common->encrypt_servaddr.sin_addr, '\0', NULL);  
  25.       
  26.     //内核态udp通信地址使用struct msghdr封装  
  27.     common->encrypt_msg.msg_name = &common->encrypt_servaddr;  
  28.     common->encrypt_msg.msg_namelen = sizeof(common->encrypt_servaddr);  
  29.   
  30.     //创建套接字,类似socket()函数,返回的sock指针就是后面数据传递用的套接字了  
  31.     ret = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);  
  32.     if (ret < 0 || NULL == sock) {  
  33.         ERROR(common, "init encrypt board socket fail\n");  
  34.         return ret;  
  35.     }  
  36.     common->encrypt_sock = sock;  
  37.   
  38.     common->encrypt_pkt = kmalloc(sizeof(struct data_pkt), GFP_KERNEL);  
  39.     if (NULL == common->encrypt_pkt)  
  40.         return -1;  
  41.   
  42.     return 0;  
  43. }  
  44.   
  45. static void encrypt_socket_close(struct fsg_common *common)  
  46. {  
  47.     //关闭套接字,类似用户态的close()函数  
  48.     sock_release(common->encrypt_sock);  
  49.     common->encrypt_sock = NULL;  
  50. }  
  51.   
  52. static int encrypt_data(struct fsg_common *common, u8* data, unsigned int size, loff_t offset)  
  53. {  
  54.     struct socket *sock = common->encrypt_sock;   
  55.     struct data_pkt *pkt = common->encrypt_pkt;  
  56.     struct sockaddr *pservaddr = (struct sockaddr *)&common->encrypt_servaddr;  
  57.     int servlen = sizeof(common->encrypt_servaddr);  
  58.   
  59.     if (unlikely(NULL == sock || NULL == pkt || NULL == pservaddr))  
  60.         return -1;  
  61.   
  62.     memset(pkt, 0, sizeof(struct data_pkt));  
  63.     unsigned int copied_size = 0;  
  64.     struct kvec vec;  
  65.     struct msghdr msg;  
  66.     memset(&msg, 0, sizeof(msg));  
  67.   
  68.     while (copied_size < size) {  
  69.         pkt->res=0xffffffff;  
  70.         pkt->file_offset = offset;   
  71.         memcpy(pkt->data, data + copied_size, SECTOR_SIZE);  
  72.   
  73.         //配置udp发送数据地址及长度  
  74.         vec.iov_base = (void *)pkt;  
  75.         vec.iov_len = sizeof(struct data_pkt);  
  76.         ret = kernel_sendmsg(sock, &common->encrypt_msg, &vec, 1, sizeof(struct data_pkt));  
  77.         printk("send data(return :%d):\n", ret);  
  78.   
  79.         //接收udp报文  
  80.         ret = kernel_recvmsg(sock, &msg, &vec, 1, sizeof(struct data_pkt), 0);  
  81.         printk("recv data(return :%d):\n", ret);  
  82.         memcpy(data+copied_size, pkt->data, 512);  
  83.         copied_size += 512;  
  84.     }     
  85.   
  86.     return 0;  
  87. }
0 0
原创粉丝点击