以两个不相关的进程来说明进程间如何通过共享内存来进行通信。其中一个文件shmread.c创建共享内存,并读取其中的信息,另一个文件shmwrite.c向共享内存中写入数据。为了方便操作和数据结构的统一,为这两个文件定义了相同的数据结构,定义在文件shmdata.c中。结构shared_use_st中的written作为一个可读或可写的标志,非0:表示可读,0:表示可写,text则是内存中的文件。
shmdata.h的源代码如下:
#ifndef _SHMDATA_H_HEADER
#define _SHMDATA_H_HEADER
#define TEXT_SZ 2048
struct shared_use_st
{
int written; // 作为一个标志,非0:表示可读,0:表示可写
char text[TEXT_SZ]; // 记录写入 和 读取 的文本
};
#endif
源文件shmread.c的源代码如下:
#include <stddef.h> #include <sys/shm.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include "shmdata.h" int main( int argc, char **argv) { void *shm = NULL; struct shared_use_st *shared; // 指向shm int shmid; // 共享内存标识符 // 创建共享内存 shmid = shmget((key_t)1234, sizeof ( struct shared_use_st), 0666|IPC_CREAT); if (shmid == -1) { fprintf (stderr, "shmat failed\n" ); exit (EXIT_FAILURE); } // 将共享内存连接到当前进程的地址空间 shm = shmat(shmid, 0, 0); if (shm == ( void *)-1) { fprintf (stderr, "shmat failed\n" ); exit (EXIT_FAILURE); } printf ( "\nMemory attached at %X\n" , ( int )shm); // 设置共享内存 shared = ( struct shared_use_st*)shm; // 注意: shm有点类似通过 malloc() 获取到的内存,所以这⾥需要做个 类型强制转换 shared->written = 0; while (1) // 读取共享内存中的数据 { // 没有进程向内存写数据,有数据可读取 if (shared->written == 1) { printf ( "You wrote: %s" , shared->text); sleep(1); // 读取完数据,设置written使共享内存段可写 shared->written = 0; // 输⼊了 end,退出循环(程序) if ( strncmp (shared->text, "end" , 3) == 0) { break ; } } else // 有其他进程在写数据,不能读取数据 { sleep(1); } } // 把共享内存从当前进程中分离 if (shmdt(shm) == -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); } 源⽂件shmwrite.c的源代码 #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/shm.h> #include "shmdata.h" int main( int argc, char **argv) { void *shm = NULL; struct shared_use_st *shared = NULL; char buffer[BUFSIZ + 1]; // 用于保存输入的文本 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); } // 将共享内存连接到当前的进程地址空间 shm = shmat(shmid, ( void *)0, 0); if (shm == ( void *)-1) { fprintf (stderr, "shmat failed\n" ); exit (EXIT_FAILURE); } printf ( "Memory attched at %X\n" , ( int )shm); // 设置共享内存 shared = ( struct shared_use_st *)shm; while (1) // 向共享内存中写数据 { // 数据还没有被读取,则等待数据被读取,不能向共享内存中写入文本 while (shared->written == 1) { sleep(1); printf ( "Waiting...\n" ); } // 向共享内存中写入数据 printf ( "Enter some text: " ); fgets (buffer, BUFSIZ, stdin); strncpy (shared->text, buffer, TEXT_SZ); // 写完数据,设置written使共享内存段可读 shared->written = 1; // 输入了end,退出循环(程序) if ( strncmp (buffer, "end" , 3) == 0) { break ; } } // 把共享内存从当前进程中分离 if (shmdt(shm) == -1) { fprintf (stderr, "shmdt failed\n" ); exit (EXIT_FAILURE); } sleep(2); exit (EXIT_SUCCESS); } 再来看看运行的结果: 分析: 1、程序shmread创建共享内存,然后将它连接到自己的地址空间。在共享内存的开始处使用了一个结构struct_use_st。该结构中有个标志written,当共享内存中有其他进程向它写入数据时,共享内存中的written被设置为0,程序等待。当它不为0时,表示没有进程对共享内存写入数据,程序就从共享内存中读取数据并输出,然后重置设置共享内存中的written为0,即让其可被shmwrite进程写入数据。 2、程序shmwrite取得共享内存并连接到自己的地址空间中。检查共享内存中的written,是否为0,若不是,表示共享内存中的数据还没有被完,则等待其他进程读取完成,并提示用户等待。若共享内存的written为0,表示没有其他进程对共享内存进行读取,则提示用户输入文本,并再次设置共享内存中的written为1,表示写完成,其他进程可对共享内存进行读操作。
|