在使用內存映射操作文件之前,我們先按照常規的方式來讀寫文件,這種方式操作如下:
1,打開或創建文件,得到文件描述符,
2,將內存中的數據以一定的格式和順序寫入文件,或者將文件中的數據以一定的格式和順序讀入到內存;
3,關閉文件描述符;
下邊是按照常規方式操作固定格式的文件的方法,包含讀寫兩個示例;
-
#include <stdlib.h>
-
#include <stdio.h>
-
#include <unistd.h>
-
#include <fcntl.h>
-
#include <string.h>
-
<strong>
-
struct student{
-
char name[20];
-
short age;
-
float score;
-
char sex;
-
};
-
int main()
-
{
-
struct student stu[5];
-
mode_t mode;
-
mode=umask(000);
-
int fd=open("user.dat",O_RDWR|O_CREAT|O_EXCL,00666);
-
if(fd==-1){
-
printf("open:%m\n");
-
umask(mode);
-
exit(-1);
-
}
-
printf("ok\n");
-
memset(stu,0,sizeof(stu));
-
int i=0;
-
for(;i<5;i++){
-
memcpy(stu[i].name,"tom",strlen("tom")+1);
-
stu[i].age=i;
-
stu[i].score=89.12f;
-
stu[i].sex='m';
-
write(fd,&stu[i],sizeof(stu[i]));
-
}
-
close(fd);
-
umask(mode);
-
return 0;
-
}
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <unistd.h>
-
#include <fcntl.h>
-
#include <string.h>
-
-
typedef struct{
-
char name[20];
-
short age;
-
float score;
-
char sex;
-
}Student;
-
<strong>
-
int main()
-
{
-
Student stu[5];
-
mode_t mode;
-
mode=umask(0000);
-
int fd=open("user.dat",O_RDWR,0666);
-
if(fd==-1){
-
printf("open:%m\n");
-
umask(mode);
-
exit(-1);
-
}
-
printf("open ok! can read;\n");
-
int i=0;
-
for(;i<5;i++){
-
read(fd,&stu[i],sizeof(stu[i]));
-
}
-
close(fd);
-
i=0;
-
for(;i<5;i++){
-
printf("stu[%d].name=%s\n",i,stu[i].name);
-
printf("stu[%d].age=%d\n",i,stu[i].age);
-
printf("stu[%d].sex=%c\n",i,stu[i].sex);
-
printf("stu[%d].score=%f\n",i,stu[i].score);
-
}
-
umask(mode);
-
return 0;
-
}
以上操作文件的方式只能操作小文件,如果文件很大,就無法一次載入內存操作,我們就需要用到內存映射技術來操作;具體實現如下:
1,首先打開文件,使用的函數原型如下:
int open( //返回值:大於等於0代表操作成功,返回打開的文件描述符號,=-1,創建或者打開失敗,失敗可查閱errorno來獲取具體錯誤信息
const char *pathname, //要打開的文明名
int flags, //打開的方式,打開方式包括:O_RDONLY 只讀方式 O_WRONLY 只寫,O_RDWR讀寫,O_CREAT創建,O_EXCL文件如果存在,使用此標記,會返回錯誤
mode_t mode); //指定創建文件的權限,只對創建文件有效,對於打開無效;
2,獲取文件大小
int fstat(int fd,//文件描述符號
struct stat*buf);//返回文件屬性結構體
返回值:成功返回0;失敗返回-1
3,把文件映射成虛擬內存
void *mmap(void *addr, //從進程的那個地址開始映射,如果爲NULL,由系統指定;
size_t length, //映射的地址空間的大小
int prot, //內存的保護模式
int flags,//映射模式 有匿名,私有,保護等標記 具體查詢man手冊;
int fd, //如果爲文件映射,則此處爲文件的描述符號
off_t offset);//如果爲文件映射,則此處代表定位到文件的那個位置,然後開始向後映射。
返回值:映射成功,返回首地址;
4,通過對內存的讀寫來實現對文件的讀寫
通常使用:memset 和memcpy來實現操作;
5,卸載映射
int munmap(void *addr, //要卸載的內存的地址
size_t length);//內存的大小
6,關閉文件
int close(int fd); //要關閉的文件描述符號 ,成功返回0,錯誤返回-1,錯誤參照errorno;
下邊是讀取文件的操作:
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <unistd.h>
-
#include <fcntl.h>
-
#include <sys/mman.h>
-
#include <sys/stat.h>
-
typedef struct{
-
char name[20];
-
short age;
-
float score;
-
char sex;
-
}student;
-
int main()
-
{
-
student *p,*pend;
-
-
int fd;
-
-
fd=open("user.dat",O_RDWR);
-
if(fd==-1){
-
fd=open("user.dat",O_RDWR|O_CREAT,0666);
-
if(fd==-1){
-
printf("打開或創建文件失敗:%m\n");
-
exit(-1);
-
}
-
}
-
-
printf("open ok!\n");
-
-
struct stat st;
-
-
int r=fstat(fd,&st);
-
if(r==-1){
-
printf("獲取文件大小失敗:%m\n");
-
close(fd);
-
exit(-1);
-
}
-
int len=st.st_size;
-
-
p=mmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
-
if(p==NULL || p==(void*)-1){
-
printf("映射失敗:%m\n");
-
close(fd);
-
exit(-1);
-
}
-
-
pend=p;
-
-
int i=0;
-
while(i<(len/sizeof(student)))
-
{
-
printf("第%d個條\n",i);
-
printf("name=%s\n",p[i].name);
-
printf("age=%d\n",p[i].age);
-
printf("score=%f\n",p[i].score);
-
printf("sex=%c\n",p[i].sex);
-
i++;
-
}
-
-
munmap(p,len);
-
-
close(fd);
-
}
-
轉:http://blog.csdn.net/lvbian/article/details/16341973