如何在 C 中与 Linux 一起使用共享内存

新手上路,请多包涵

我的一个项目有点问题。

我一直在尝试找到一个有据可查的示例,该示例将共享内存与 fork() 一起使用,但没有成功。

基本上情况是,当用户启动程序时,我需要在共享内存中存储两个值: current_pathchar*file_name 也是 char*

根据命令参数,新进程以 fork() 启动,该进程需要读取和修改存储在共享内存中的 current_path 变量,而 file_name 变量是只读的。

是否有一个关于共享内存的好教程以及您可以指导我的示例代码(如果可能)?

原文由 bleepzter 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 704
2 个回答

有两种方法: shmgetmmap 。我将讨论 mmap ,因为它更现代、更灵活,但如果您更愿意使用旧式工具,可以查看 man shmget或本教程) .

mmap() 函数可用于分配具有高度可定制参数的内存缓冲区以控制访问和权限,并在必要时使用文件系统存储支持它们。

以下函数创建一个进程可以与其子进程共享的内存缓冲区:

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

void* create_shared_memory(size_t size) {
  // Our memory buffer will be readable and writable:
  int protection = PROT_READ | PROT_WRITE;

  // The buffer will be shared (meaning other processes can access it), but
  // anonymous (meaning third-party processes cannot obtain an address for it),
  // so only this process and its children will be able to use it:
  int visibility = MAP_SHARED | MAP_ANONYMOUS;

  // The remaining parameters to `mmap()` are not important for this use case,
  // but the manpage for `mmap` explains their purpose.
  return mmap(NULL, size, protection, visibility, -1, 0);
}

下面是一个使用上面定义的函数来分配缓冲区的示例程序。父进程会写一条消息,fork,然后等待其子进程修改缓冲区。两个进程都可以读取和写入共享内存。

 #include <string.h>
#include <unistd.h>

int main() {
  char parent_message[] = "hello";  // parent process will write this message
  char child_message[] = "goodbye"; // child process will then write this one

  void* shmem = create_shared_memory(128);

  memcpy(shmem, parent_message, sizeof(parent_message));

  int pid = fork();

  if (pid == 0) {
    printf("Child read: %s\n", shmem);
    memcpy(shmem, child_message, sizeof(child_message));
    printf("Child wrote: %s\n", shmem);

  } else {
    printf("Parent read: %s\n", shmem);
    sleep(1);
    printf("After 1s, parent read: %s\n", shmem);
  }
}

原文由 slezica 发布,翻译遵循 CC BY-SA 4.0 许可协议

这是共享内存的示例:

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define SHM_SIZE 1024  /* make it a 1K shared memory segment */

int main(int argc, char *argv[])
{
    key_t key;
    int shmid;
    char *data;
    int mode;

    if (argc > 2) {
        fprintf(stderr, "usage: shmdemo [data_to_write]\n");
        exit(1);
    }

    /* make the key: */
    if ((key = ftok("hello.txt", 'R')) == -1) /*Here the file must exist */
{
        perror("ftok");
        exit(1);
    }

    /*  create the segment: */
    if ((shmid = shmget(key, SHM_SIZE, 0644 | IPC_CREAT)) == -1) {
        perror("shmget");
        exit(1);
    }

    /* attach to the segment to get a pointer to it: */
    if ((data = shmat(shmid, NULL, 0)) == (void *)-1) {
        perror("shmat");
        exit(1);
    }

    /* read or modify the segment, based on the command line: */
    if (argc == 2) {
        printf("writing to segment: \"%s\"\n", argv[1]);
        strncpy(data, argv[1], SHM_SIZE);
    } else
        printf("segment contains: \"%s\"\n", data);

    /* detach from the segment: */
    if (shmdt(data) == -1) {
        perror("shmdt");
        exit(1);
    }

    return 0;
}

脚步 :

  1. 使用 ftok 将路径名和项目标识符转换为 System V IPC 密钥

  2. 使用 shmget 分配一个共享内存段

  3. 使用 shmat 将 shmid 标识的共享内存段附加到调用进程的地址空间

  4. 对内存区域进行操作

  5. 使用 shmdt 分离

原文由 Mayank 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏