要求:
Please use shmgetsystem call create a shared memory and use it, and explain how shared memoryimplements.
程序运行:
程序通过shmid=shmget(0x44,1024,IPC_CREAT|0600);创建了一块共享内存,一次运行可得到其key值为65537,然后与shimd绑定,创建一个子进程,子进程通过共享内存写入“A Happy Day !”,在退出后再次输出父进程的结果为“A Happy Day !”,所以共享内存实现。
共享内存:
共享内存是运行在同一台机器上的进程间通信最快的方式,因为数据不需要在不同的进程间复制。通常由一个进程创建一块共享内存区,其余进程对这块内存区进行读写。得到共享内存有两种方式:映射/dev/mem设备和内存映像文件。前一种方式不给系统带来额外的开销,但在现实中并不常用,因为它控制存取的将是实际的物理内存,在Linux系统下,这只有通过限制Linux系统存取的内存才可以做到,这当然不太实际。常用的方式是通过shmXXX函数族来实现利用共享内存进行存储的。
首先要用的函数是shmget,它获得一个共享存储标识符。
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, int size, int flag);
这个函数有点类似大家熟悉的malloc函数,系统按照请求分配size大小的内存用作共享内存。Linux系统内核中每个IPC结构都有的一个非负整数的标识符,这样对一个消息队列发送消息时只要引用标识符就可以了。这个标识符是内核由IPC结构的关键字得到的,这个关键字,就是上面第一个函数的key。数据类型key_t是在头文件sys/types.h中定义的,它是一个长整形的数据。在我们后面的章节中,还会碰到这个关键字。
当共享内存创建后,其余进程可以调用shmat()将其连接到自身的地址空间中。
void *shmat(int shmid, void *addr, int flag);
shmid为shmget函数返回的共享存储标识符,addr和flag参数决定了以什么方式来确定连接的地址,函数的返回值即是该进程数据段所连接的实际地址,进程可以对此进程进行读写操作。
使用共享存储来实现进程间通信的注意点是对数据存取的同步,必须确保当一个进程去读取数据时,它所想要的数据已经写好了。通常,信号量被要来实现对共享存储数据存取的同步,另外,可以通过使用shmctl函数设置共享存储内存的某些标志位如SHM_LOCK、SHM_UNLOCK等来实现。
程序运行截图:
附录源代码:
#include<stdio.h>
#include<stdlib.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/stat.h>
int main()
{
int i;
int shmid;
char *shared;
shmid=shmget(0x44,1024,IPC_CREAT|0600);
printf("%d\n",shmid);
shared=(char*)shmat(shmid,0,0);
if(fork() ==0)
{
sleep(2);
sprintf(shared,"A Happy Day!");
exit(0);
}
printf("%s\n",shared );
shmdt(shared);
return 0;
}