共享内存深入理解(2)

int main(int argc, char* argv[])
{
    int flag = O_RDWR;
    int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    int fd = 0;
    unsigned char* ptr, c;
    fd = shm_open("/shm_test", flag, mode);
    if (-1 == fd)
    {
        printf("open shm failed!\n");
        return 1;
    }
    struct stat stat;
    fstat(fd,&stat);
    ptr = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    close(fd);

for (int i = 0; i < stat.st_size; i++)
    {
        *ptr++ = i % 256;
        printf("write %d\n",i);
    }
    return 0;
}

这里与mqueue不同的是,read端读取的时候并不会阻塞等待,如果没有提前write内容到共享内存里,read读取到的内容为空。

3、共享内存的起始地址

同一共享内存区对象映射到不同进程的地址空间,起始地址可以不一样。

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

int main(int argc, char* argv[])
{
    int fd1,fd2;
    unsigned char *ptr1, *ptr2;
    pid_t pid;
    int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    fd1 = shm_open("/shm_test",O_RDWR,mode);
    if (fd1 == -1)
    {
        printf("Message : %s\n", strerror(errno));
        return 1;
    }

struct stat stat;
    fstat(fd1, &stat);

fd2 = open("/dev/shm/shm_test1",O_RDWR | O_CREAT,mode);
    if (fd2 == -1)
    {
        printf("Message : %s\n", strerror(errno));
        return 1;
    }
   
    pid = fork();
    if (pid == 0)
    {
        ptr2 = mmap(NULL, 4, PROT_READ|PROT_WRITE, MAP_SHARED, fd2,0);
        ptr1 = mmap(NULL, 1024, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0);
        printf("child: shm ptr=%p, mmf ptr=%p\n",ptr1, ptr2);
        sleep(5);
        printf("share memory integer:%d", *ptr1);
    }
    else if (pid > 0)
    {
        ptr1 = mmap(NULL, 1024, PROT_READ|PROT_WRITE, MAP_SHARED, fd1, 0);
        ptr2 = mmap(NULL, 4, PROT_READ|PROT_WRITE, MAP_SHARED, fd2,0);
        printf("parent: shm ptr=%p, mmf ptr=%p\n",ptr1, ptr2);
        *ptr1 = 128;
        waitpid(0, NULL, 0);
    }
    else{
       
    }

return 0;
}

代码运行结果如下:

可见,在不同的进程中,相同的共享内存区对象起始地址可以不一样。

一、进程间通信-管道 https://www.linuxidc.com/Linux/2018-04/151680.htm

二、进程间通信-命名管道 https://www.linuxidc.com/Linux/2018-04/151681.htm

三、进程间通信-消息队列 https://www.linuxidc.com/Linux/2018-04/151682.htm

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/12868.html