进程间通信之内存映射与管道函数的应用

来源:互联网 发布:网络翻唱女歌手曼里 编辑:程序博客网 时间:2024/06/01 11:14

一:内存映射

mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问。从而实现多进程对于同一个量的访问。

头文件:#include <unistd.h>    #include <sys/mman.h>

定义函数:void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offsize);

函数说明:mmap()用来将某个文件内容映射到内存中,对该内存区域的存取即是直接对该文件内容的读写。

参数说明:

参数 说明start 指向欲对应的内存起始地址,通常设为NULL,代表让系统自动选定地址,对应成功后该地址会返回。length 代表将文件中多大的部分对应到内存。prot  代表映射区域的保护方式,有下列组合:

  • PROT_EXEC  映射区域可被执行;
  • PROT_READ  映射区域可被读取;
  • PROT_WRITE  映射区域可被写入;
  • PROT_NONE  映射区域不能存取。
flags 会影响映射区域的各种特性:
  • MAP_FIXED  如果参数 start 所指的地址无法成功建立映射时,则放弃映射,不对地址做修正。通常不鼓励用此旗标。
  • MAP_SHARED  对应射区域的写入数据会复制回文件内,而且允许其他映射该文件的进程共享。
  • MAP_PRIVATE  对应射区域的写入操作会产生一个映射文件的复制,即私人的”写入时复制” (copy on write)对此区域作的任何修改都不会写回原来的文件内容。
  • MAP_ANONYMOUS  建立匿名映射,此时会忽略参数fd,不涉及文件,而且映射区域无法和其他进程共享。
  • MAP_DENYWRITE  只允许对应射区域的写入操作,其他对文件直接写入的操作将会被拒绝。
  • MAP_LOCKED  将映射区域锁定住,这表示该区域不会被置换(swap)。

在调用mmap()时必须要指定MAP_SHARED 或MAP_PRIVATE。fd open()返回的文件描述词,代表欲映射到内存的文件。offset 文件映射的偏移量,通常设置为0,代表从文件最前方开始对应,offset必须是分页大小的整数倍。返回值:若映射成功则返回映射区的内存起始地址,否则返回MAP_FAILED(-1),错误原因存于errno 中。

错误代码:

  • EBADF  参数fd 不是有效的文件描述词。
  • EACCES  存取权限有误。如果是MAP_PRIVATE 情况下文件必须可读,使用MAP_SHARED 则要有PROT_WRITE 以及该文件要能写入。
  • EINVAL  参数start、length 或offset 有一个不合法。
  • EAGAIN  文件被锁住,或是有太多内存被锁住。
  • ENOMEM  内存不足。

二:管道

多进程之间的通信方式之一,通过read与Write函数实现变量的值之间的传递,从而能实现进程的通信

1. 函数说明

pipe(建立管道):
1) 头文件 #include<unistd.h>
2) 定义函数: int pipe(int filedes[2]);
3) 函数说明: pipe()会建立管道,并将文件描述词由参数filedes数组返回。
              filedes[0]为管道里的读取端
              filedes[1]则为管道的写入端。
4) 返回值:  若成功则返回零,否则返回-1,错误原因存于errno中。

    错误代码:
         EMFILE 进程已用完文件描述词最大量
         ENFILE 系统已无文件描述词可用。
         EFAULT 参数 filedes 数组地址不合法。


三:编程案例

    int pipes[2];    int main(int argc,char **argv)    {        int num[4]={1,2,3,4};        int temp = 10;        int *p_map = &temp;        pid_t pid;        p_map=(int*)mmap(NULL,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);            pipe(pipes);        pid = fork();        if(pid == 0)        {            printf("son 1 :num[1] = %d,*p_map = %d \n",num[1]);            sleep(1);            *p_map = 100;            num[1] = 5;            write(pipes[1],num,sizeof(num));            printf("son 2 :num[1] = %d,*p_map = %d \n",num[1]);        }        else        {            sleep(2);            printf("father 1:num[1] = %d,*p_map = %d \n",num[1],*p_map);            read(pipes[0],num,sizeof(num));            printf("father 2:num[1] = %d,*p_map = %d \n",num[1],*p_map);        }        return 0;    }

0 0
原创粉丝点击