*******************************************************************************
进程间通信方式之一: 共享内存
进程1:创建共享内存1和共享内存2,并初始化共享内存1为0,并输出初始化之后的共享内存1的内容,然后重新给共享内存1赋予新的内容并输出该内容;与此同时给共享内存2赋予一定的内容并输出,之后再sleep 60秒,删除共享内存1和共享内存2。
进程2:在进程1运行的时候(进程1在sleep 60秒的时候),连接共享内存1和共享内存2并输出共享内存里面的内容。
运行结果:运行环境 Linux
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~终端1~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[root@localhost shm]# gcc -g strlen1.c -o strlen1 //编译
[root@localhost shm]# gcc -g strlen2.c -o strlen2
[root@localhost shm]# ./strlen1 //运行进程1
***************************************
shmget1 ok. //创建共享内存1
shmat1 ok.
shmget2 ok. //创建共享内存2
shmat2 ok.
***************************************
~~~~~~~~~~~~~~~Result0~~~~~~~~~~~~~~~~~
The 1th before shm1 info is : //初始化共享内存1 输出的初始化之后的内容
00000000
00000000
~~~~~~~~~~~~~~~Result0~~~~~~~~~~~~~~~~~
=======================================
Please input two long number : //给共享内存1中输入新的内容
255
65535
a[0]=ff,a[1]=ffff,a[0]=255,a[1]=65535 //分别为十六进制输出和十进制输出
Please input a string and lenth<24 :
//给共享内存2中输入新的内容,注意共享内存2并没有初始化。
wo ai ni ma
=======================================
~~~~~~~~~~~~~~~Result0~~~~~~~~~~~~~~~~~
The 2th after shm1 info is :
ff000000
ffff0000
The shm2 info is :
wo ai ni ma
~~~~~~~~~~~~~~~Result0~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~Result1~~~~~~~~~~~~~~~~~
The 1th before shm1 info is :
00000000
00000000
~~~~~~~~~~~~~~~Result1~~~~~~~~~~~~~~~~~
=======================================
Please input two long number :
888888
65535
a[0]=d9038,a[1]=ffff,a[0]=888888,a[1]=65535
Please input a string and lenth<24 :
ke xiao
=======================================
~~~~~~~~~~~~~~~Result1~~~~~~~~~~~~~~~~~
The 2th after shm1 info is :
38900d00
ffff0000
The shm2 info is :
ke xiao
~~~~~~~~~~~~~~~Result1~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~Result2~~~~~~~~~~~~~~~~~
The 1th before shm1 info is :
00000000
00000000
~~~~~~~~~~~~~~~Result2~~~~~~~~~~~~~~~~~
=======================================
Please input two long number :
12345678
111111
a[0]=bc614e,a[1]=1b207,a[0]=12345678,a[1]=111111
Please input a string and lenth<24 :
fang huo xiang
=======================================
~~~~~~~~~~~~~~~Result2~~~~~~~~~~~~~~~~~
The 2th after shm1 info is :
4e61bc00
07b20100
The shm2 info is :
fang huo xiang
~~~~~~~~~~~~~~~Result2~~~~~~~~~~~~~~~~~
***************************************
shm1 shmdt ok. //断开与共享内存1的连接
shmctl1 ok. //删除共享内存1
shm2 shmdt ok.
shmctl2 ok.
***************************************
[root@localhost shm]#
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~终端2~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[root@localhost shm]# ./strlen2 //在终端1 sleep 60秒的时候,在终端2运行进程2
**************************************
shmget1 ok.
shmat1 ok. //连接共享内存
shmget2 ok
shmat2 ok.
**************************************
~~~~~~~~~~~~~~~~~~Result0~~~~~~~~~~~~~ //每隔10秒输出一次共享内存的内容
shm1 info is : //当前共享内存1的内容
00000000
00000000
shm2 info is : //当前共享内存2里面美誉内容
~~~~~~~~~~~~~~~~~~Result0~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~Result1~~~~~~~~~~~~~
shm1 info is : //当前共享内存1中的内容发生了变化
ff000000
ffff0000
shm2 info is :
~~~~~~~~~~~~~~~~~~Result1~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~Result2~~~~~~~~~~~~~
shm1 info is :
ff000000
ffff0000
shm2 info is :
wo ai ni ma
~~~~~~~~~~~~~~~~~~Result2~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~Result3~~~~~~~~~~~~~
shm1 info is :
00000000
00000000
shm2 info is :
wo ai ni ma
~~~~~~~~~~~~~~~~~~Result3~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~Result4~~~~~~~~~~~~~
shm1 info is :
38900d00
ffff0000
shm2 info is :
ke xiao
~~~~~~~~~~~~~~~~~~Result4~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~Result5~~~~~~~~~~~~~
shm1 info is :
00000000
00000000
shm2 info is :
ke xiao
~~~~~~~~~~~~~~~~~~Result5~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~Result6~~~~~~~~~~~~~
shm1 info is :
00000000
00000000
shm2 info is :
ke xiao
~~~~~~~~~~~~~~~~~~Result6~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~Result7~~~~~~~~~~~~~
shm1 info is :
4e61bc00
07b20100
shm2 info is :
fang huo xiang
~~~~~~~~~~~~~~~~~~Result7~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~Result8~~~~~~~~~~~~~
shm1 info is :
4e61bc00
07b20100
shm2 info is :
fang huo xiang
~~~~~~~~~~~~~~~~~~Result8~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~Result9~~~~~~~~~~~~~
shm1 info is :
4e61bc00
07b20100
shm2 info is :
fang huo xiang
~~~~~~~~~~~~~~~~~~Result9~~~~~~~~~~~~~
**************************************
shm1 shmdt ok.
shm2 shmdt ok.
**************************************
[root@localhost shm]#
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
改进:
在进程1中每隔10秒重新给共享内存1、共享内存2填充新的内容并输出,不断运行
进程2(每十秒中输出共享内存1和共享内存2中的内容),查看内存内容是否同步。
另外,有可能发生进程1正在给共享内存1填充内容,与此同时进程2正好访问共享内存1,结果是什么样的,怎样修改需要实验。
可以考虑信号量,互斥量。
注意:
在进程1即将结束的时候,运行进程2,当进程1结束后,共享内存1和共享内存2已经被
进程1删除了,但是连接到进程2的共享内存1和共享内存2,并没有断开连接,进程2会一直输出最后保存在共享内存里面的内容(映射到该进程2空间的共享内存)
*******************************************************************************
进程1
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>
int main(){
char *shmaddr1=NULL;
int *shmaddr2=NULL;
int shmid1;
int shmid2;
int ret;
long a[2];
unsigned char *blk_tp=NULL;
int i=0;
char str[24];
int count=0; //可以注释掉
printf("***************************************\n");
shmid1 = shmget((key_t)123,24,IPC_CREAT|IPC_EXCL);
//创建共享内存1,24个字节
if(-1 == shmid1){
printf(" shmget1 error. \n");
return -1;
}else{
printf(" shmget1 ok. \n");
}
shmaddr1 = shmat(shmid1,0,SHM_RND); //将该共享内存1映射到该进程空间
if(-1 == (long)shmaddr1){
printf(" shmat1 error. \n");
return -1;
}else{
printf(" shmat1 ok. \n");
}
shmid2 = shmget((key_t)234,24,IPC_CREAT|IPC_EXCL); //创建共享内存2
if(-1 == shmid2){
printf(" shmget2 error. \n");
return -1;
}else{
printf(" shmget2 ok. \n");
}
shmaddr2 = shmat(shmid2,0,SHM_RND); //将共享内存2映射到该进程空间
if(-1 == (long)shmaddr2){
printf(" shmat2 error. \n");
return -1;
}else{
printf(" shmat2 ok. \n");
}
printf("***************************************\n");
printf("\n");
while(count<3) //这个循环输入可以注释掉,仅仅一次就可以验证共享内存是同步的
{ //这个可以注释掉
printf("~~~~~~~~~~~~~~~Result%d~~~~~~~~~~~~~~~~~\n",count);
// printf("sizeof(shmaddr1) is %d \n",sizeof(shmaddr1));
//此次输出仅仅是shmaddr1指针的大小
memset(shmaddr1,0x00,sizeof(a)); //将该共享内存1初始化为0
blk_tp=(unsigned char*)shmaddr1;
i=2*sizeof(long);
printf("The 1th before shm1 info is : \n");
while(i>=4){ //初始化之后,输出该共享内存的内容,每四个字节输出一次
printf(" %02x%02x%02x%02x \n",*blk_tp,*(blk_tp+1),*(blk_tp+2),*(blk_tp+3));
blk_tp+=4;
i -= 4;
}
printf("~~~~~~~~~~~~~~~Result%d~~~~~~~~~~~~~~~~~\n",count);
printf("\n");
sleep(4);
memset(a,0,sizeof(a)); //初始化数组a
// printf("sizeof(long) is %d, sizeof(a) is %d. \n",sizeof(long),sizeof(a));
printf("=======================================\n");
printf("Please input two long number : \n");
scanf("%ld %ld",&a[0],&a[1]); //初始化数组a 一个long是4个字节
getchar();
printf("a[0]=%0x,a[1]=%0x,a[0]=%ld,a[1]=%ld \n",a[0],a[1],a[0],a[1]);
memmove(shmaddr1,a,sizeof(a)); //将共享内存1的内容设置为a数组里面的内容
// printf("strlen(shmaddr1) is %d. \n",strlen((char *)shmaddr1));
printf("Please input a string and lenth<24 : \n");
gets(str); //给共享内存2重新填充新的内容
memmove(shmaddr2,str,24);
printf("=======================================\n");
// printf("strlen(shmaddr2) is %d. \n",strlen((char *)shmaddr2));//求该共享内存的大小
blk_tp=(unsigned char*)shmaddr1;
i=2*sizeof(long);
printf("\n");
printf("~~~~~~~~~~~~~~~Result%d~~~~~~~~~~~~~~~~~\n",count);
printf("The 2th after shm1 info is : \n");
while(i>=4){ //重新输出共享内存1的内容
printf(" %02x%02x%02x%02x \n",*blk_tp,*(blk_tp+1),*(blk_tp+2),*(blk_tp+3));
blk_tp+=4;
i -= 4;
}
printf("The shm2 info is : \n %s \n",shmaddr2); //输出共享内存2的内容
printf("~~~~~~~~~~~~~~~Result%d~~~~~~~~~~~~~~~~~\n",count);
count++;
sleep(10);
//sleep 10秒,等待验证进程间数据共享,先运行strlen1,之后再运行strlen2,验证进程间数//据共享
}//这个可以注释掉
sleep(20);
printf("\n");
printf("***************************************\n");
ret = shmdt(shmaddr1); //该进程和共享内存1,断开连接
if(-1 == ret)
{
printf(" shm1 shmdt errno. \n");
}else{
printf(" shm1 shmdt ok. \n");
}
ret = shmctl(shmid1,IPC_RMID,0); //删除共享内存1
if(-1 == ret){
printf(" shmctl1 errno. \n");
}else{
printf(" shmctl1 ok. \n");
}
ret = shmdt(shmaddr2); //该进程和共享内存2,断开连接
if(-1 == ret)
{
printf(" shm2 shmdt errno. \n");
}else{
printf(" shm2 shmdt ok. \n");
}
ret = shmctl(shmid2,IPC_RMID,0); //删除共享内存2
if(-1 == ret){
printf(" shmctl2 errno. \n");
}else{
printf(" shmctl2 ok. \n");
}
printf("***************************************\n");
return 0;
}
进程2
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>
int main(){
char *shmaddr1=NULL;
int *shmaddr2=NULL;
int shmid1;
int shmid2;
int ret;
int i=0;
unsigned char *blk_tp=NULL;
long a[2];
int count=0; //这个可以注释掉
printf("**************************************\n");
shmid1 = shmget((key_t)123,0,0); //连接共享内存1
if(-1 == shmid1){
printf(" shmget1 error. \n");
return -1;
}else{
printf(" shmget1 ok. \n");
}
shmaddr1 = shmat(shmid1,0,SHM_RND); //将共享内存1映射到该进程空间
if(-1 == (long)shmaddr1){
printf(" shmat1 error. \n");
return -1;
}else{
printf(" shmat1 ok. \n");
}
shmid2 = shmget((key_t)234,0,0); //连接共享内存2
if(-1 == shmid2){
printf(" shmget2 error. \n");
return -1;
}else{
printf(" shmget2 ok \n");
}
shmaddr2 = shmat(shmid2,0,SHM_RND); //将共享内存2映射到该进程空间
if(-1 == (long)shmaddr2){
printf(" shmat2 error. \n");
return -1;
}else{
printf(" shmat2 ok. \n");
}
printf("**************************************\n");
printf("\n");
while(count<10) //这个可以注释掉
{ //可以注释掉
printf("~~~~~~~~~~~~~~~~~~Result%d~~~~~~~~~~~~~\n",count);
// printf("strlen(shmaddr1) is %d. \n",strlen(shmaddr1)); //求共享内存1的大小
blk_tp=(unsigned char*)shmaddr1;
i=2*sizeof(long);
printf("shm1 info is : \n");
while(i>=4){ //输出该共享内存1的内容
printf(" %02x%02x%02x%02x \n",*blk_tp,*(blk_tp+1),*(blk_tp+2),*(blk_tp+3));
blk_tp+=4;
i -= 4;
}
// printf("strlen(shmaddr2) is %d. \n",strlen((char *)shmaddr2));
//求共享内存2的大小
printf("shm2 info is : \n %s \n",shmaddr2); //输出共享内存2的内容
printf("~~~~~~~~~~~~~~~~~~Result%d~~~~~~~~~~~~~\n",count);
count++;
sleep(10);
} //可以注释掉
printf("\n");
printf("*****************************************\n");
ret = shmdt(shmaddr1); //该进程和共享内存1,断开连接
if(-1 == ret)
{
printf(" shm1 shmdt errno. \n");
}else{
printf(" shm1 shmdt ok. \n");
}
ret = shmdt(shmaddr2); //该进程和共享内存2,断开连接
if(-1 == ret)
{
printf(" shm2 shmdt errno. \n");
}else{
printf(" shm2 shmdt ok. \n");
}
printf("*****************************************\n");
return 0;
}