文件I/O-mmap

定义

参数



注意事项


文件与内存映射

// 修改文件内存映射
#include <stdio.h>
#include <sys/mman.h> // mmap
#include <sys/stat.h> // open
#include <sys/types.h> // open
#include <fcntl.h> // open
#include <unistd.h> // lseek,write
#include <string.h> // memcpy
int main(int argc, char *argv[]) {
int fd;
char *mapped_mem, *p;
int flength = 1024;
//void * start_addr = 0;
fd = open(argv[1], O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR);
flength = lseek(fd, 1, SEEK_END);
write(fd, "\0", 1);
lseek(fd, 0, SEEK_SET);
mapped_mem = (char *)mmap( NULL, // 系统自己决定映射区起始地址
flength, // 映射区数据长度
PROT_READ, // 映射区保护方式
MAP_PRIVATE, // 共享方式
fd,
0);
/*使用映射区域*/
printf("%s\n", mapped_mem);
close(fd);
munmap(mapped_mem, flength); // 删除内存映射
return 0;
}

修改文件的内存映像

#include <stdio.h>
#include <sys/mman.h> // mmap
#include <sys/stat.h> // open
#include <sys/types.h> // open
#include <fcntl.h> // open
#include <unistd.h> // lseek,write
#include <string.h> // memcpy
int main(int argc, char *argv[]) {
int fd;
char *mapped_mem, *p;
int flength = 1024;
fd = open(argv[1], O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR);
flength = lseek(fd, 1, SEEK_END);
write(fd, "\0", 1);
lseek(fd, 0, SEEK_SET);
mapped_mem = (char *)mmap( NULL, // 系统自己决定映射区起始地址
flength, // 映射区数据长度
PROT_READ | PROT_WRITE, // 映射区保护方式
MAP_SHARED, // 共享方式
fd,
0);
/*使用映射区域*/
printf("%s\n", mapped_mem);
while ((p = strstr(mapped_mem, "ass"))) {
memcpy(p, "123", 3);
p += 3;
}
close(fd);
munmap(mapped_mem, flength); // 删除内存映射
return 0;
}

mmap用法示例(1)

  • 下面代码的功能: 创建一个新文件,设置文件大小,使用mmap函数映射文件地址出来,对地址直接拷贝数据进入,再取消映射。 这时再打开文件,数据已经存放到到文件中了。演示通过mmap映射文件地址方式读写文件。
    https://juejin.cn/post/7058533534503272462
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#define MAX 1024
int main(int argc, char *argv[])
{
// 参数初始化
int fd;
// 配置参数
if (argc != 2)
{
printf("usage:./exe filename\n");
exit(EXIT_FAILURE); // 包含的头文件,<stdlib.h>
}
// 创建文件
// #define fileName file.txt
//char fileName[MAX];
//strcpy(fileName, (const)argv[1]);
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; // S_IRWXU;
fd = open(argv[1], O_CREAT | O_RDWR, mode); // O_EXCL如果文件存在则报错
if (fd == -1)
{
perror("Error open func.\n");
exit(EXIT_FAILURE);
}
// 设置文件大小
ftruncate(fd, MAX); // fd文件大小修改为指定大小
// 获取文件大小
struct stat st;
fstat(fd, &st);
printf("%s size is %d Byte.\n", argv[1], st.st_size);
// 映射文件到内存空间
unsigned char * mem_p = NULL;
mem_p = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (mem_p == NULL)
{
perror("Error mmap func.\n");
close(fd);
exit(EXIT_FAILURE);
}
// 关闭文件
close(fd);
// 实现文件读写
strcpy(mem_p, "mmap func test.\n");
// 打印文件内容
printf("mem_p = %s\n", mem_p);
// 改为大小字母
for (int i = 0; i < st.st_size; i++)
{
mem_p[i] = toupper(mem_p[i]);
putchar(mem_p[i]);
}
// 取消映射
if (munmap(mem_p, st.st_size) == -1)
{
perror("Error munmap func.\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}

多线程并发拷贝数据

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
#include <wait.h>
#include <pthread.h>
#define FORK_NUM 4
/*
多进程并发拷贝大文件
*/
int main(int argc, char * argv[])
{
// 参数处理
if (argc != 3)
{
printf("usage:./exe <a> <b>\n");
exit(EXIT_FAILURE);
}
// 打开源文件
int src_fd = open(argv[1], O_RDWR);
if (src_fd == -1)
{
perror("Error open func.\n");
exit(EXIT_FAILURE);
}
// 创建新文件
int new_fd = open(argv[2], O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (new_fd == -1)
{
perror("Error open func new.\n");
exit(EXIT_FAILURE);
}
// 获取源文件大小,设置新文件大小
struct stat src_st;
fstat(src_fd, &src_st);
printf("src_fd size is:%d.\n", src_st.st_size);
ftruncate(new_fd, src_st.st_size);
// 映射源文件到内存空间
unsigned char * src_p;
src_p = mmap(NULL, src_st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, src_fd, 0);
if (src_p == NULL)
{
close(src_fd);
perror("Error mmap func.\n");
exit(EXIT_FAILURE);
}
unsigned char * new_p;
new_p = mmap(NULL, src_st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, new_fd, 0);
if (new_p == NULL)
{
close(new_fd);
perror("Error mmap func.\n");
exit(EXIT_FAILURE);
}
// 关闭文件
close(new_fd);
close(src_fd);
// 计算子进程和父进程拷贝文件字节大小
int cp_size = 0;
int main_size = 0;
cp_size = src_st.st_size / FORK_NUM;
main_size = src_st.st_size % FORK_NUM;
// 创建子进程
int i;
for (i = 0; i < FORK_NUM; i++)
{
if (fork() == 0)
break;
}
// 子进程完成文件的拷贝
if (i < FORK_NUM) // 子进程
{
memcpy(new_p + i * cp_size, src_p + i * cp_size, cp_size);
munmap(new_p, src_st.st_size);
munmap(src_p, src_st.st_size);
}
else // 父进程
{
memcpy(new_p + i * cp_size, src_p + i * cp_size, main_size);
munmap(new_p, src_st.st_size);
munmap(src_p, src_st.st_size);
pid_t pid;
while (1)
{
pid = wait(NULL);
if (pid == -1)
break;
printf("%d thread over.\n", pid);
}
printf("%d main thread over.\n", pid);
}
exit(EXIT_SUCCESS);
}
posted @   steve的miao  阅读(58)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示