您的位置:首页 > 其它

mmap的使用及pcap文件解析示例

2016-12-29 15:19 435 查看
mmap能够通过将磁盘上的文件映射到内存中,通过指针访问文件内容。这样能够达到快速处理文件。包含的头文件为#include <sys/mman.h>,主要使用的函数有://打开文件,获取文件描述符int open(const char *pathname, int flags);//获取文件字节数int stat(const char *restrict path, struct stat *restrict buf);//使用mmap将对应的文件映射到本进程内存 void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);   //解除隐射才能释放内存空间int munmap(void *addr, size_t length);//关闭文件 int close(int fd);注意:使用完mmap之后,要记得使用munmap函数释放内存空间,否则就会产生内存泄露,而且此内存泄露不易发现,使用valgrind也没能查出来。以下以我处理pcap文件的函数为例,展示mmap的使用方法,示例代码片段如下:
#include <sys/mman.h>#include <sys/stat.h>#include <pcap.h>#include <stdio.h>#include <stdlib.h>#include <string.h>int parseAPcapfile(char * file_name) {struct pcap_pkthdr pkt_hdr;struct eth_hdr ethhdr;struct ip_hdr iphdr;struct stat statbuf;long file_size;int i;int pcap_fd;char *origin_data, *data, *flow_ptr;//get file description/* file open failed. return FILE_OPEN_ERROR. */pcap_fd = open(file_name, O_RDONLY);if(-1 == pcap_fd){printf("ERROR:file open error!\n");return FILE_OPEN_ERROR;}//get file bytes//file_size = lseek(pcap_fd, 0, SEEK_END);stat(file_name,&statbuf);file_size = statbuf.st_size;if(file_size < 24) {close(pcap_fd);printf("pcap file is damaged!\n");return FILE_DAMAGED;}//get mmap pointerorigin_data = (char *)mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, pcap_fd, 0);data = origin_data;printf("file size is: %ld\n", file_size);//if(strlen(data) < 24 ||  0xA1B2C3D4 != *(uint32_t*)data) {if(0xA1B2C3D4 != *(uint32_t*)data) {printf("read pcap failed: invailied file magic: %x\n", *(uint32_t*)data);munmap(origin_data, file_size);origin_data = NULL;data = NULL;close(pcap_fd);return FILE_MAGIC_ERROR;}data += 24;while (data - origin_data < file_size) {/** start to parse a flow* get a start pointer of a flow*/flow_ptr = data;/** parse the pcap header of a flow*/pkt_hdr.ts.tv_sec = *(uint32_t *)flow_ptr;flow_ptr += 4;pkt_hdr.ts.tv_usec = *(uint32_t *)flow_ptr;flow_ptr += 4;pkt_hdr.caplen = *(uint32_t *)flow_ptr;flow_ptr += 4;pkt_hdr.len = *(uint32_t *)flow_ptr;flow_ptr += 4;//Print PCAP header//printPcapHeader(pkt_hdr);/** Start to parse a flow that captured from network interface* no need to convert to host sequence: MAC address/ string /uint8_t* need to convert to host sequence: uint16_t<ntohs()>/ uint32_t<ntohl()>** parse the Ethernet header of a flow*/ethhdr = *(struct eth_hdr*)flow_ptr;flow_ptr += ETHERNET_HEADER_LEN;//print ethernet information//printEthHeader(ethhdr);//if proto is not IP proto, then continue.if(ntohs(ethhdr.proto) != ETH_P_IP) {//next flowprintf("the flow is not ip proto\n");data += (pkt_hdr.caplen + 16);continue;}/** Start to parse the IP header* get the ip header*/iphdr = *(struct ip_hdr *)flow_ptr;// print the ip header//printIpInfo(iphdr);parseIpHeader(iphdr);//next flowdata += (pkt_hdr.caplen + 16);}//free mmap spacemunmap(origin_data, file_size);//close fileclose(pcap_fd);if (data - origin_data == file_size) {printf("have processed  %d bytes data!\n", data - origin_data);origin_data = NULL;data = NULL;return FILE_PROCESS_SUCCESS;} else {origin_data = NULL;data = NULL;printf("ERROR: only processed  %d bytes data!\n", data - origin_data);return FILE_PROCESS_FAILED;}}
                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息