利用mmap實(shí)現(xiàn)文件拷貝功能
利用mmap實(shí)現(xiàn)的一個(gè)文件拷貝例子,供大家參考,具體內(nèi)容如下
/*
* gcc -Wall -O3 -o copy_mmap copy_mmap.c
*/
#include < stdio.h >
#include < stdlib.h >
#include < string .h > /* for memcpy */
#include < strings.h >
#include < sys / mman.h >
#include < sys / types.h >
#include < sys / stat.h >
#include < fcntl.h >
#include < unistd.h >
#define PERMS 0600
int main ( int argc, char * argv[] )
{
int src, dst;
void * sm, * dm;
struct stat statbuf;
if ( argc != 3 )
{
fprintf( stderr, " Usage: %s \n " , argv[ 0 ] );
exit( EXIT_FAILURE );
}
if ( ( src = open( argv[ 1 ], O_RDONLY ) ) < 0 )
{
perror( " open source " );
exit( EXIT_FAILURE );
}
/* 為了完成復(fù)制,必須包含讀打開,否則mmap()失敗 */
if ( ( dst = open( argv[ 2 ], O_RDWR | O_CREAT | O_TRUNC, PERMS ) ) < 0 )
{
perror( " open target " );
exit( EXIT_FAILURE );
}
if ( fstat( src, & statbuf ) < 0 )
{
perror( " fstat source " );
exit( EXIT_FAILURE );
}
/*
* 參看前面man手冊(cè)中的說明,mmap()不能用于擴(kuò)展文件長度。所以這里必須事
* 先擴(kuò)大目標(biāo)文件長度,準(zhǔn)備一個(gè)空架子等待復(fù)制。
*/
if ( lseek( dst, statbuf.st_size - 1 , SEEK_SET ) < 0 )
{
perror( " lseek target " );
exit( EXIT_FAILURE );
}
if ( write( dst, & statbuf, 1 ) != 1 )
{
perror( " write target " );
exit( EXIT_FAILURE );
}
/* 讀的時(shí)候指定 MAP_PRIVATE 即可 */
sm = mmap( 0 , ( size_t )statbuf.st_size, PROT_READ,
MAP_PRIVATE | MAP_NORESERVE, src, 0 );
if ( MAP_FAILED == sm )
{
perror( " mmap source " );
exit( EXIT_FAILURE );
}
/* 這里必須指定 MAP_SHARED 才可能真正改變靜態(tài)文件 */
dm = mmap( 0 , ( size_t )statbuf.st_size, PROT_WRITE,
MAP_SHARED, dst, 0 );
if ( MAP_FAILED == dm )
{
perror( " mmap target " );
exit( EXIT_FAILURE );
}
memcpy( dm, sm, ( size_t )statbuf.st_size );
/*
* 可以不要這行代碼
*
* msync( dm, ( size_t )statbuf.st_size, MS_SYNC );
*/
return ( EXIT_SUCCESS );
}
mmap()好處是處理大文件時(shí)速度明顯快于標(biāo)準(zhǔn)文件I/O,無論讀寫,都少了一次用戶空間與內(nèi)核空間之間的復(fù)制過程。操作內(nèi)存還便于設(shè)計(jì)、優(yōu)化算法。
文件I/O操作/proc/self/mem不存在頁邊界對(duì)齊的問題,但至少Linux的mmap()的最后一個(gè)形參offset并未強(qiáng)制要求頁邊界對(duì)齊,如果提供的值未對(duì)齊,系統(tǒng)自動(dòng)向上舍入到頁邊界上。malloc()分配得到的地址不見得對(duì)齊在頁邊界上。
/proc/self/mem和/dev/kmem不同。root用戶打開/dev/kmem就可以在用戶空間訪問到內(nèi)核空間的數(shù)據(jù),包括偏移0處的數(shù)據(jù),系統(tǒng)提供了這樣的支持。顯然代碼段經(jīng)過/proc/self/mem可寫映射后已經(jīng)可寫,無須mprotect()介入。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
基于C++11實(shí)現(xiàn)手寫線程池的示例代碼
在實(shí)際的項(xiàng)目中,使用線程池是非常廣泛的,本文主要介紹了基于C++11實(shí)現(xiàn)手寫線程池的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-08-08
C++項(xiàng)目開發(fā)實(shí)現(xiàn)圖書管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++項(xiàng)目開發(fā)實(shí)現(xiàn)圖書管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
C++語言實(shí)現(xiàn)線性表之?dāng)?shù)組實(shí)例
這篇文章主要介紹了C++語言實(shí)現(xiàn)線性表之?dāng)?shù)組,實(shí)例分析了C++實(shí)現(xiàn)數(shù)組形式線性表的原理與方法,需要的朋友可以參考下2015-04-04
C利用語言實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)之隊(duì)列
隊(duì)列 (Queue):簡(jiǎn)稱隊(duì),是另一種限定性的線性表,它只允許在表的一端插入元素,而在另一端刪除元素。q=(a1, a2, a3, … an),其中a1為隊(duì)頭,an為隊(duì)尾,下面文章小編將為大家詳細(xì)介紹,需要的下伙伴可以參考一下2021-10-10
C# CLR 中學(xué)習(xí) C++關(guān)鍵詞extern使用詳解
這篇文章主要為大家介紹了C# CLR 中學(xué)習(xí) C++ 之extern使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
C++調(diào)用C函數(shù)報(bào)錯(cuò)無法解析的外部命令/無法解析的外部符號(hào)問題
這篇文章主要介紹了C++調(diào)用C函數(shù)報(bào)錯(cuò)無法解析的外部命令/無法解析的外部符號(hào)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08

