POSIX 共享内存

更新时间:
2024-05-29
下载文档

POSIX 共享内存

虽然管道和 POSIX 命名消息队列都能实现进程间的数据通信,但当数据量较大时,管道和 POSIX 命名消息队列的效率就有点低了,这时建议使用 POSIX 共享内存进行直接的数据通信。

为了避免有多个写者进程对同一块共享内存进行写操作,通常需要使用一个命名信号量作为该共享内存的写锁。

同时为了让读者进程能及时知道写者进程已经修改共享内存的内容,通常需要使用一个命名信号量作为该共享内存的读通知信号。

创建一个 POSIX 共享内存可以使用 shm_open 函数。shm_open 函数指定了 POSIX 共享内存的设备文件路径,其他进程可以使用 shm_open 函数打开该共享内存,shm_open 函数返回一个文件描述符,使用 mmap 函数映射该共享内存到进程的虚拟空间内,mmap 函数返回一个虚拟地址,之后便可以通过这个虚拟地址对共享内存进行读和写操作,从而达到高效的进程间直接大数据量通信的目的。

#include <sys/mman.h>
int shm_open(const char *name, int oflag, mode_t mode);

函数 shm_open 与一般的 open 功能是一样的,只是它在共享内存设备上打开或创建一个文件。其原型分析如下:

  • 此函数成功返回文件描述符,失败返回-1 并设置错误号。
  • 参数 name 为用于内存共享映射的文件名称。共享内存创建成功后会在/dev/shm/name生成对应的文件。
  • 参数 oflag 为操作标识,如 O_CREAT、O_RDWR 等。
  • 参数 mode 为创建文件的模式。

当一个 POSIX 共享内存使用完毕后,应该调用 close 函数将其关闭,如果共享内存不再有任何用途时,应该调用 shm_unlink 函数将其删除,SylixOS 将回收该共享内存占用的内核资源。

下面程序是两个进程(server 和 client)通过共享内存进行通信的例程。

服务器端:

#include <stdio.h>
#include <string.h>
#include <sys/mman.h>

int main (int argc, char **argv)
{
    int     fd;
    void   *addr;

    fd = shm_open("test", O_RDWR | O_CREAT, 0666);
    if (fd < 0) {
        perror("shm_open");
        return  (-1);
    }

    ftruncate(fd, 1024);

    addr = mmap(NULL, 1024, PROT_WRITE, MAP_SHARED, fd, 0);
    if (addr == MAP_FAILED) {
        perror("mmap");
        return  (-1);
    }

    memcpy(addr, "hello sylixos", strlen("hello sylixos") + 1);

    msync(addr, 1024, MS_SYNC);
    sleep(2);
    munmap(addr, 1024);

    close(fd);
    shm_unlink("test");

    return  (0);
}

客户端:

#include <stdio.h>
#include <string.h>
#include <sys/mman.h>

int main (int argc, char **argv)
{
    int     fd;
    void   *addr;
    char    r_buf[64] = {0};

    fd = shm_open("test", O_RDWR, 0);
    if (fd < 0) {
        perror("shm_open");
        return  (-1);
    }

    ftruncate(fd, 1024);

    addr = mmap(NULL, 1024, PROT_READ, MAP_SHARED, fd, 0);
    if (addr == MAP_FAILED) {
        perror("mmap");
        return  (-1);
    }

    memcpy(r_buf, addr,strlen("hello sylixos") + 1);

    printf("r_buf: %s\n", r_buf);
    munmap(addr, 1024);
    close(fd);

    return  (0);
}

在 SylixOS Shell 中执行两个程序,首次启动服务器端,来创建共享内存文件,随后再启动客户端来打开已经创建的共享内存,并读取共享内存中的数据,执行结果如下:

# ./server
# ./client
r_buf: hello sylixos

通过执行结果可以看出服务器写入字符串 "hello sylixos",客户端成功获取了该字符串。

文档内容是否对您有所帮助?
有帮助
没帮助