linux+mmap父子通信_Linux进程通信之mmap

mmap()函数:

void *mmap(void* addr,size_t length,int port,int flags,int fd,off_t offset);

返回:成功:返回创建的映射区首地址;失败:MAP_FAILED 宏

参数:

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

length:   欲创建映射区的大小

port:    映射区权限PROT _READ、PROT_WRITE 、PROT _READ|PROTWRITE

flags:   标志位参数(常用于设定更新物理区域、设置共享、创建匿名映射区)

MAP_SHARED:     会将映射区所做的操作反射到物理设备上

MAP_PRIVATE:     映射区所作的修改不会反映到物理设备。

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

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

/***

mmap.c

***/#include#include#include#include#include#include

intmain()

{intlen,ret;char *p =NULL;int fd = open("mytest.txt",O_CREAT|O_RDWR,0644);if(fd < 0)

{

perror("open error:");

exit(1);

}

len= ftruncate(fd,4);if(-1 ==len)

{

perror("ftruncate error:");

exit(1);

}

p= mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);if(p ==MAP_FAILED)

{

perror("mmap error:");

exit(1);

}

strcpy(p,"abc");

ret= munmap(p,4);if(-1 ==ret)

{

perror("mmap error:");

exit(1);

}

close(fd);return 0;

}

运行结果:

ubuntu1604@ubuntu:~/wangqinghe/linux/20190807$ gcc mmap.c -o mmap

ubuntu1604@ubuntu:~/wangqinghe/linux/20190807$ ./mmap

ubuntu1604@ubuntu:~/wangqinghe/linux/20190807$ cat mytest.txt

abc

mmap在使用过程中注意以下事项:

创建映射区的过程中,隐含着一次对映射文件的读操作。

当MAP_SHARED时,要求:映射区的权限  <= 文件打开的权限(出于对映射区的保护)。而MAP_PRIVATE则无所谓,因为mmap中的权限时对内存的限制。

映射区的释放和文件关闭无关。只要映射成功,文件可以立刻关闭。

特别注意:当映射文件大小为0时,不能创建映射区。所以:用于映射的文件必须有实际大小。mmap使用时常常会出现总线错误,通常是因为共享文件存储空间大小所引起的。

munmap传入的地址一定是mmap的返回地址,坚决杜绝指针++操作

如果使用文件偏移,则值必须是4K的整数倍

mmap创建映射区出错概率极高,一定要检查返回值,确保映射区建立成功再进行后续操作。

mmap父子进程间通信:

文件inode属性

struct stat

{

存储指针地址;

大小;

权限;

类型;

所以者;

}

/***

mmap_fork.c

***/#include#include#include#include#include#include

int var = 100;intmain()

{int *p;

pid_t pid;intfd;

fd= open("temp",O_RDWR|O_CREAT|O_TRUNC,0644);if(fd < 0)

{

perror("open error");

exit(1);

}

unlink("temp");

ftruncate(fd,4);

p= (int*)mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);if(p ==MAP_FAILED)

{

perror("mmap error");

exit(1);

}

close(fd);

pid=fork();if(0 ==pid)

{*p = 2000;var = 1000;

printf("child, *p = %d, var = %d\n",*p,var);

}else{

sleep(1);

printf("parent, *p = %d, var = %d\n",*p,var);

wait(NULL);int ret = munmap(p,4);if(-1 ==ret)

{

perror("munmap error");

exit(1);

}

}return 0;

}

运行结果:

ubuntu1604@ubuntu:~/wangqinghe/linux/20190807$ gcc mmap_fork.c -o mmap_fork

ubuntu1604@ubuntu:~/wangqinghe/linux/20190807$ ./mmap_fork

child, *p = 2000, var = 1000

parent, *p = 2000, var = 100

mmap创建匿名映射区

/***

fork_mmap_linux.c

***/#include#include#include#include#include#include

int var = 100;intmain()

{int *p;

pid_t pid;

p= (int*)mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_SHARED | MAP_ANON,-1,0);if(p ==MAP_FAILED)

{

perror("mmap error");

exit(1);

}

pid=fork();if(0 ==pid)

{var = 1000;*p = 2000;

printf("child, *p = %d,var = %d\n",*p,var);

}else{

sleep(1);//printf("parent,*p = %d\n",*p);

printf("child, *p = %d,var = %d\n",*p,var);

wait(NULL);int ret = munmap(p,4);if(-1 ==ret)

{

perror("munmap error");

exit(1);

}

}return 0;

}

运行结果:

ubuntu1604@ubuntu:~/wangqinghe/linux/20190807$ gcc fork_map_linux.c -o fork_map_linux

ubuntu1604@ubuntu:~/wangqinghe/linux/20190807$ ./fork_map_linux

child, *p = 2000,var = 1000

child, *p = 2000,var = 100

注意:MAP_ANONYMOUS和MAP_ANON 这两个宏是linux操作系统特有的宏,再类Unix系统中如无该宏的定义,可以使用以下步骤来完成匿名映射区的建立。

fd = open(“/dev/zero”,O_RDWR);

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

/***

fork_map_anon.c

***/#include#include#include#include#include#include

int var = 100;intmain()

{int *p;

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

p= (int*)mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);if(p ==MAP_FAILED)

{

perror("mmap error");

exit(1);

}

pid=fork();if(0 ==pid)

{var = 1000;*p = 2000;

printf("child, *p = %d,var = %d\n",*p,var);

}else{

sleep(1);//printf("parent,*p = %d\n",*p);

printf("child, *p = %d,var = %d\n",*p,var);

wait(NULL);int ret = munmap(p,4);if(-1 ==ret)

{

perror("munmap error");

exit(1);

}

}return 0;

}

运行结果:

buntu1604@ubuntu:~/wangqinghe/linux/20190807$ gcc fork_map.c -o fork_map

ubuntu1604@ubuntu:~/wangqinghe/linux/20190807$ ./fork_map

child, *p = 2000,var = 1000

child, *p = 2000,var = 100

mmap无血缘关系进程间通信:

/***

mmap_w.c

***/#include#include#include#include#include#include#include

structSTU

{intid;char name[20];charsex;

};void sys_err(char *str)

{

perror(str);

exit(1);

}int main(int argc,char **argv)

{intfd;struct STU student = {10,"xiaoming",'m'};char *mm;if(argc < 2)

{

printf("./a.out file_shared\n");

exit(-1);

}

fd= open(argv[1],O_RDWR | O_CREAT,0664);

ftruncate(fd,sizeof(student));

mm= mmap(NULL,sizeof(student),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);if(mm ==MAP_FAILED)

{

sys_err("mmap error");

}

close(fd);while(1)

{

memcpy(mm,&student,sizeof(student));

student.id++;

sleep(2);

}

munmap(mm,sizeof(student));return 0;

}

/***

mmap_r.c

***/#include#include#include#include#include#include#include

structSTU

{intid;char name[20];charsex;

};void sys_err(char *str)

{

perror(str);

exit(1);

}int main(int argc,char **argv)

{intfd;structSTU student;struct STU *mm;if(argc < 2)

{

printf("./a.out file_shared\n");

exit(-1);

}

fd= open(argv[1],O_RDONLY);if(-1 ==fd)

sys_err("open error");

mm= mmap(NULL,sizeof(student),PROT_READ,MAP_SHARED,fd,0);if(mm ==MAP_FAILED)

{

sys_err("mmap error");

}

close(fd);while(1)

{

printf("id=%d,name = %s,%c\n",mm->id,mm->name,mm->sex);

sleep(2);

}

munmap(mm,sizeof(student));return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值