操作系统练习:进程间通信(共享内存方式)

说明

本文是《操作系统概念(第九版)》3.4节“进程间通信”的练习。

进程间通信主要由两种模型:

  • 共享内存
  • 消息传递

本文使用共享内存的方式实现进程间的通信

file

创建消息生产者

创建生产者的主要操作包括:

  • 定义共享内存的大小、名称,以及通信消息的具体message内容
  • 定义共享内存的对象和内存映射文件指针
  • 用shm_open()方法,实例化共享内存对象(其参数包括共享内存名称和对象权限等)
  • 用ftruncate()方法,配置共享内存对象的大小
  • 用mmap()方法,创建内存映射文件,以便包含共享内存对象,它返回一个指向内存映射文件的指针,可用其访问共享内存对象
  • 最后,对共享内存的写入,是通过调用sprintf()方法和向内存映射文件指针写入格式化字符串实现(每次写入之后,都要用所写字节的数量递增指针)

创建生产者的详细代码如下,可以新建一个producer.c文件,然后将代码拷贝进去:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>

int main() {
    
    
        /* the size of shared memory object */
        const int SIZE = 4096;

        /* name of the shared memory object */
        const char *name = "OS";

        /* strings written to the shared memory */
        const char *message_0 = "Hello";
        const char *message_1 = "World!";


        /* shared memory file descriptor */
        int shm_fd;

        /* pointer to shared memory object */
        void *ptr;

        /* create the shared memory object */
        shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);

        /* configure the size of the shared memory object */
        ftruncate(shm_fd, SIZE);

        /* memory map the shared memory object */
        ptr = mmap(0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0);


        /* write to the shared memory object */
        sprintf(ptr, "%s", message_0);
        ptr += strlen(message_0);
        sprintf(ptr, "%s", message_1);
        ptr += strlen(message_1);

        printf("Written done!");
        return 0;
}

创建消息消费者

创建消费者的代码和创建消费者的代码有一些类似的地方,但是也有一些区别:

  • 不需要创建一个共享内存对象,而是通过名称去打开一个共享内存对象
  • 访问内存对象之后,调用了shm_unlink()方法移除了共享内存段

创建消费者的详细代码如下,可以新建一个consumer.c文件,然后将下列代码拷贝进去:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(){
    
    
        /* the size of shared memory object */
        const int SIZE = 4096;

        /* name of the shared memory object */
        const char *name = "OS";

        /* shared memory file descriptor */
        int shm_fd;

        /* pointer to shared memory object */
        void *ptr;


        /* open the shared memory object */
        shm_fd = shm_open(name, O_RDONLY, 0666);

        /* memory map the shared memory object */
        ptr = mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);

        /* read from the shared memory object */
        printf("%s", (char *)ptr);

        /* remove the shared memroy object */
        shm_unlink(name);

        printf("\n");
        printf("Read done!\n");

        return 0;
}

编译和运行

接下来是编译两个c文件,然后执行生产者代码,最后执行消费者代码

# 编译生产者代码
gcc -o producer producer.c -lrt

## 编译消费者代码
gcc -o consumer consumer.c -lrt 

## 执行生产者代码
./producer

## 执行消费者代码
./consumer

最终的执行效果如下:
file

报错处理

致命错误:stlib.h:没有那个文件或目录

如果有下面的报错,那么是因为引用的文件名称错误,正确的应该是 #include <stdlib.h> (我看到的书上少了一个‘d’)

扫描二维码关注公众号,回复: 17142946 查看本文章
producer.c:6:10: 致命错误:sys/stath:没有那个文件或目录
 #include <sys/stath>
          ^~~~~~~~~~~
编译中断。

错误:‘O_RDRW’ undeclared (first use in this function); did you mean ‘O_RDWR’?

如果是下面的报错,则应该将O_RDRW改成O_RDWR

producer.c:27:36: 错误:‘O_RDRW’ undeclared (first use in this function); did you mean ‘O_RDWR’?
  shm_fd = shm_open(name, O_CREAT | O_RDRW, 0666);
                                    ^~~~~~
                                    O_RDWR
producer.c:27:36: 附注:每个未声明的标识符在其出现的函数内只报告一次

file

‘PROT_WRITE’ undeclared, ‘MAP_SHARED’未声明

以下报错,需要新增两个文件引用:

  • #include <sys/mman.h>
  • #include <unistd.h>
producer.c:33:22: 错误:‘PROT_WRITE’ undeclared (first use in this function); did you mean ‘S_IWRITE’?
  ptr = mmap(0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0);
                      ^~~~~~~~~~
                      S_IWRITE
producer.c:33:34: 错误:‘MAP_SHARED’未声明(在此函数内第一次使用)
  ptr = mmap(0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0);
                                  ^~~~~~~~~~

file

对‘shm_open’未定义的引用

解决办法: 在编译命令最后加 -lrt

/tmp/ccnkitBK.o:在函数‘main’中:
producer.c:(.text+0x39):对‘shm_open’未定义的引用
collect2: 错误:ld 返回 1

猜你喜欢

转载自blog.csdn.net/weixin_42534940/article/details/131882483