Linux系统编程之mmap

1. void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset);

addr: 建立映射区的首地址,由Linux内核指定,使用时直接传递NULL;

length:欲创建映射区的大小。

prot: 映射区权限 PROT_READ, PROT_WRITE, PROT_READ | PROT_WRITE

flags:标志位参数(常用于设定更新物理区域、设置共享、创建匿名映射区) MAP_SHARED: 会将映射区所做的操作反映到物理设备(磁盘)上;MAP_PRIVATE: 映射区所做的修改不会映射到物理设备;

         当用于父子进程通信时,MAP_SHARED表示映射区由父子进程共享,MAP_PRIVATE表示映射区由进程独享,所以IPC时需要SHARED。

fd: 用来建立映射区的文件描述符

offset: 映射文件的偏移(4K的整数倍)

返回值: 成功返回创建的映射区首地址;失败返回: MAP_FAILED((void*)-1)

#include <stdio.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>

int var = 100;
int main(void)
{
		int fd = open("test.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
		if (fd < 0)
		{
				perror("open error");
				exit(1);
		}
		if (ftruncate(fd, 4) < 0)
		{
				perror("ftruncate error");
				exit(1);
		}
		unlink("test.txt");
		
		int* p = mmap(NULL, 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
		if (p == MAP_FAILED)
		{
				perror("mmap error");
				exit(1);
		}

        // mmap建立完成后即可close fd了
		close(fd);

        pid_t pid = fork();
		if (pid < 0)
		{
				perror("fork error");
				exit(1);
		}
		if (pid == 0)
		{
				// 子进程
				*p = 1234;
				var = 1000;
				printf("child process:*p = %d, var = %d\n", *p, var);	
		}
		else
		{
				sleep(1);
                // var属于进程独享,所以不受影响
                // 当mmap是MAP_PRIVATE时,*p就不是子进程所更改的了而是0,map区域属于进程独享
				printf("parent process: *p = %d, var = %d\n", *p, var);
				wait(NULL);
		}

		if (munmap(p, 4) < 0)
		{
				perror("munmap error");
				exit(1);
		}

		return 0;	

}

2.mmap参数注意事项

  length不能为0,也就是说文件大小不能为0;

  munmap的地址必须和mmap出来的地址相同。

  文件open时的权限和mmap的prot的选项:映射区的权限  <= 文件的打开权限; 建立映射区时隐含一次读操作

  offset必须是4K的整数倍,因为映射区是MMU建立的,MMU划分物理内存的最小单位是4K(一页的大小)。

文件描述符先关闭对mmap没影响,因为fd相当于文件句柄,操作文件的方式,而现在是在用映射区操作文件,不再需要fd,所以一旦mmap建立成功,即可关闭fd。

3. 结束时要调用munmap

int munmap(void* addr, size_t length);

返回值:成功返回0, 失败返回-1.

4. mmap父子进程间通信

父子进程共享:打开的文件;mmap建立的映射区(但必须指定MAP_SHARED).

5. 匿名映射:只支持Linux系统,类Unix需要另一种方法。

flag位加上MAP_ANONYMOUS(或者MAP_ANNO), 即MAP_SHARED | MAO_ANONYMOUS, 文件描述符用-1, 文件大小任意。

例如:int* p = mmap(NULL, 4, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);  --> 注意文件大小任意

类Unix系统需要下面两步来完成匿名映射区:

fd = open("/dev/zero", O_RDWR);

p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

6. 在无血缘关系进程间通信:进程间打开的文件路径一样即可

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值