mmap

下面是一個很簡單、很一般的程式碼,內容是使用 openssl 所提供的函式去計算一個檔案的 MD5。既然這麼簡單為什麼要紀錄呢?理由有兩個:第一,紀錄一下要怎麼使用 openssl 的 library;第二是今天的重點,mmap。

一般來說,要計算一個檔案的 MD5,勢必要把整個檔案讀到記憶體當中(或是分批讀入,但勢必整個檔案都要吃進來),所以標準的程序應該是 open --> read --> md5 --> close。而在 read 這一步還需要額外準備一份記憶體空間給它。但如果使用 mmap 的話就可以直接少了 read 這一步了。


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
               
#include <openssl/md5.h>

long util_getFileSize( char * );
void util_md5File( char *, unsigned char * ); 

static long util_getFdSize( int );

int main( int argc, char *argv[] )
{
    int             fileFd = 0;
    long            fileSize = 0;
    unsigned char   md5sum[MD5_DIGEST_LENGTH];
    int             i = 0;
    
    if( argc != 2 )
    {
        printf( "Usage: md5 <file>\n" );
        return 0;
    }
    
    fileSize = util_getFileSize( argv[1] );
    
    if( fileSize == -1 )
    {
        printf( "Error!\n" );
        return 0;
    }
    
    util_md5File( argv[1], md5sum );
    
    printf( "File Name: %s\n", argv[1] );
    printf( "File Size: %lu\n", fileSize );
    printf( "MD5:\n" );
    
    for( i = 0 ; i < MD5_DIGEST_LENGTH; i++ )
    {
        if( ( i % 4 ) == 0 )
        {
            printf( "\t" );
        }
        
        printf( "%02X ", md5sum[i] );
        
        if( ( i % 4 ) == 3 )
        {
            printf( "\n" );
        }
    }
        
    return 0;
}

long util_getFileSize( char *_pFileName )
{
    int fd = open( _pFileName, O_RDONLY );
    long fileSize = 0;
    
    if( fd < 0 )
    {
        printf( "File open failed!\n" );
        return -1;
    }
    
    fileSize = util_getFdSize( fd );
        
    close( fd );
    return fileSize;
}

void util_md5File( char *_pFileName, unsigned char *_pOutput )
{
    int     fd = open( _pFileName, O_RDONLY );
    long    fileSize = 0;
    char    *_pFile = NULL;
    
    if( fd < 0 )
    {
        printf( "File open failed!\n" );
        return;
    }
    
    fileSize = util_getFdSize( fd );
    
    if( fileSize == -1 )
    {
        return;
    }
        
    _pFile = mmap( 0, fileSize, PROT_READ, MAP_SHARED, fd, 0 );
    MD5( ( unsigned char *)_pFile, fileSize, _pOutput );
    
    munmap( _pFile, fileSize );
    close( fd );
    
    return;
}

static long util_getFdSize( int fd )
{
    struct stat statbuf;
    
    if( fstat( fd, &statbuf ) < 0 )
    {
        close( fd );
        return -1;
    }
    
    return statbuf.st_size;
}



上面有顯示 mmap 的用法。要特別注意的用完以後一定要 munmap

mmap() creates a new mapping in the virtual address space of the calling process. 其他的部份在使用時再問男人吧。

留言

這個網誌中的熱門文章

如何將Linux打造成OpenFlow Switch:Openvswitch

我弟家的新居感恩禮拜分享:善頌善禱

Linux Virtual Interface: TUN/TAP