曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 6968|回复: 0
打印 上一主题 下一主题

共享内存实例2(生产者与消费者)

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34397
跳转到指定楼层
楼主
发表于 2009-9-6 16:05:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这里需要两个程序,一个是生产者,一个好似消费者。生产者负责往共享内存区写数据,消费者负责往共享内存区读数据。

共用头文件定义如下
#define    TEXT_SZ    2048

struct shared_use_st {
    int written_by_you;
    char some_text [TEXT_SZ];
};

shm1.c 是消费者程序,其负责创建共享内存区,代码如下
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <sys/shm.h>
#include "shm_com.h"

int main()
{
    int running = 1;
    void *shared_memory = (void *)0;
    struct shared_use_st *shared_stuff;
    int shmid;

    srand ((unsigned int)getpid ());
   
    shmid = shmget ((key_t)1234, sizeof (struct shared_use_st),0666 | IPC_CREAT);

    if (shmid == -1) {
        fprintf (stderr, "shmget failed\n");
        exit (EXIT_FAILURE);
    }

    /*使共享内存可被程序访问*/
    shared_memory = shmat (shmid, (void *)0, 0);

    if (shared_memory == (void *)-1) {
        fprintf (stderr, "shmat failed\n");
        exit (EXIT_FAILURE);
    }

    printf ("Memory attached at %X\n", (int)shared_memory);

    shared_stuff = (struct shared_use_st  *)shared_memory;
    shared_stuff->written_by_you = 0;

    while (running) {
        if (shared_stuff->written_by_you) {
            printf ("You wrote: %s", shared_stuff->some_text);
            sleep (rand () % 4);
            shared_stuff->written_by_you = 0;
            if (strncmp (shared_stuff->some_text, "end", 3) == 0) {
                running = 0;
            }
        }
    }
    /*与共享内存分离并删除之*/
    if (shmdt (shared_memory) == -1) {
        fprintf (stderr, "shmdt failed\n");
        exit (EXIT_FAILURE);
    }
   
    if (shmctl (shmid, IPC_RMID, 0) == -1) {
        fprintf (stderr, "shmctl(IPC_RMID) failed\n");
        exit (EXIT_FAILURE);
    }
   
    exit (EXIT_SUCCESS);
}

shm2.c 是生产者程序,代码如下
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/shm.h>
#include "shm_com.h"

int main()
{
    int running = 1;
    void *shared_memory = (void *)0;
    struct shared_use_st *shared_stuff;
    char buffer [BUFSIZ];
    int shmid;

    shmid = shmget ((key_t)1234, sizeof (struct shared_use_st), 0666 | IPC_CREAT);
   
    if (shmid == -1) {
        fprintf (stderr, "shmget failed\n");
        exit (EXIT_FAILURE);
    }
    shared_memory = shmat (shmid, (void *)0, 0);
    if (shared_memory == (void *)-1) {
        fprintf (stderr, "shmat failed\n");
        exit (EXIT_FAILURE);
    }
   
    printf ("Memory attached at %X\n", (int)shared_memory);
   
    shared_stuff = (struct shared_use_st *)shared_memory;
   
    while (running) {
        while (shared_stuff->written_by_you == 1) {
            sleep (1);
            printf ("waiting for client...\n");
        }
        printf ("Enter some text: ");
        fgets (buffer, BUFSIZ, stdin);

        strncpy (shared_stuff->some_text, buffer, TEXT_SZ);
        shared_stuff->written_by_you = 1;

        if (strncmp (buffer, "end", 3) == 0) {
            running = 0;
        }
    }
    if (shmdt (shared_memory) == -1) {
        fprintf (stderr, "shmdt failed\n");
        exit (EXIT_FAILURE);
    }
    exit (EXIT_SUCCESS);
}
运行测试
消费者
beyes@linux-beyes:~/C/share_memory> ./shm1.exe
Memory attached at B806F000
You wrote: hello consumer
You wrote: what are you doing ?
... ....
生产者
beyes@linux-beyes:~/C/share_memory> ./shm2.exe
Memory attached at B7F76000
Enter some text: hello consumer
waiting for client...
waiting for client...
waiting for client...
Enter some text: what are you doing ?
waiting for client...
waiting for client...
waiting for client...
Enter some text:
... ...
说明
在 shm2.c 中,BUFSIZ  宏在 stdio.h 里有定义,其大小为 8192 个字节。

shm1.exe 创建了共享内存区,然后将其附加到自己的地址空间上。在创建共享空间的时候,是利用 shared_use_st 结构类型的大小来指定共享空间的大小。
在 shared_use_st 结构里,有一个 written_by_you 标志,它在有可用数据可读时,就会被设置为 1 ,这时 shm1.exe 就可以读取数据并打印出来,在读取数据后,标志被清零。如果读取到 end 字符串,那么表示要退出程序,此时程序会脱掉共享内存区并删除它。

在 shm2.exe 中,在得到并附加共享内存区后,就可以往共享内存区写数据了。但是,如果它检测到 written_by_you 标志被置位,那么表名消费者(shm1.exe)端还没将数据读取,所以会进入等待状态。当 shm1.exe 标志被清除后,shm2.exe 可以继续写数据并重新置位标志。shm2.exe 在把相关内容写往共享内存区后,也会检测一下所写的内容是不是 "end" ,如果是,则会退出。

注意,使用 written_by_you 这样的标志来轮询资源效率非常低下,在实际代码中并不会这么用,取而代之的是会使用信号量,或者是传递消息,还可以是使用管道 (PIPE),还可能是发送信号等手段提供更加有效的同步机制。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-6-18 01:17 , Processed in 0.076726 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表