|
这里需要两个程序,一个是生产者,一个好似消费者。生产者负责往共享内存区写数据,消费者负责往共享内存区读数据。
共用头文件定义如下:
#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),还可能是发送信号等手段提供更加有效的同步机制。 |
|