*******************************************************************************
进程间通信方式之一:  共享内存

进程1:创建共享内存1和共享内存2,并初始化共享内存10,并输出初始化之后的共享内存1的内容,然后重新给共享内存1赋予新的内容并输出该内容;与此同时给共享内存2赋予一定的内容并输出,之后再sleep 60秒,删除共享内存1和共享内存2

进程2:在进程1运行的时候(进程1sleep 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;
}