进程间通信——共享内存

作者在 2013-07-17 17:49:20 发布以下内容

*******************************************************************************

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

 

进程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;

}

进程间通信 | 阅读 1711 次
文章评论,共0条
游客请输入验证码
最新评论