IPC之共享内存

  共享内存作为IPC(Inter-Process Communication)的一种方式,适合同一台机器上不同进程间的相互通信,由于不同进程直接对同一块"约定好"的内存进行操作,因此效率为所有IPC中最高的。

    共享内存的使用还是很简单的,主要涉及到五个函数的使用,下面一一进行介绍。

     (1)key_t ftok(const char *pathname, int proj_id);

                功能:用来创建System V IPC的一个key值

                参数:pathname:系统中真实存在的并可以访问的目录或文件

                          proj_id   :在1~255之间的数值,可以用来标识这是该进程创建的第几块共享内存

              返回值:成功则返回一个key_t值;失败返回-1.

     (2)int shmget(key_t key, size_t size, int shmflg);

 

                功能:用来创建一块共享内存

                参数:  key    :由ftok返回的值

                           size    :需要创建共享内存的大小

                           shmflg:共享内存的模式及权限标识

                                     模式可以取如下值:

                                     IPC_CREAT: 新建一块共享内存

                                     IPC_ALLOC: 使用已开辟的内存

                                     IPC_EXCL   : 如果标识符已存在,则返回错误值      

               返回值:成功则返回一个标志值;失败返回-1.

        (3)void *shmat(int shmid, const void *shmaddr, int shmflg);

 

                功能:把由shmid标识的共享内存attach到该进程的地址空间

                参数: shmid     :由shmget返回的共享内存的标志

                           shmaddr :把共享内存attach在进程地址空间的起始地址,一般设为0

                            shmflg   :进程对该内存的操作模式。SHM_RDONLY表示只读模式,其它为读写模式。

              返回值:成功则返回一个共享内存起始地址;失败返回(void *)-1.

       (4)int shmdt(const void *shmaddr);

 

 

                功能:删除一块共享内存

                参数: shmaddr :要从进程中detach的共享内存地址

              返回值:成功则返回0;失败返回-1.

       (5) int shmctl(int shmid, int cmd, struct shmid_ds *buf);

 

                功能:执行对共享内存的控制

                参数:  shmid :标志共享内存的id

                            cmd    :控制命令,可取值如下:

                                        IPC_STAT  :得到共享内存的状态 
                                        IPC_SET    :改变共享内存的状态 
                                        IPC_RMID  :删除共享内存

 

                             buf    :用来存放共享内存的状态

              返回值:失败返回-1;成功返回其他值。

      下面看两个使用共享内存通信进程的例子:

View Code
 1 //process1.cc
 2 
 3 #include <stdio.h>
 4 #include <errno.h>
 5 #include <string.h>
 6 #include <sys/shm.h>
 7 #include <sys/ipc.h>
 8 
 9 #define MAX_SHM_SIZE 1024*1024
10 
11 int main(int argc, char *argv[])
12 {
13     const char *name = "/home/pathenon/project/network";
14     int i = 1;
15 
16     key_t key = ftok(name, i);
17     if(-1 == key)
18     {
19         perror("ftok");
20         return 1;
21     }
22 
23     int shm_id=shmget(key, MAX_SHM_SIZE, IPC_CREAT|0666);
24     if(-1 == shm_id)
25     {
26         perror("shmget");
27         return 1;
28     }
29 
30     char buffer[] = "Hello share memory ipc\n";
31     char *p = (char *)shmat(shm_id, 0, 0);
32     if((void *)-1 == (void *)p)
33     {
34         perror("shmat");
35         return 1;
36     }
37 
38     //write memory
39     int size = sizeof(buffer);
40     memcpy(p, &size, 4);
41     memcpy(p+4, buffer, sizeof(buffer));
42 
43     shmdt(p);
44 
45     return 0;
46 }
View Code
 1 //process2.cc
 2 
 3 #include <stdio.h>
 4 #include <errno.h>
 5 #include <string.h>
 6 #include <sys/shm.h>
 7 #include <sys/ipc.h>
 8 
 9 #define MAX_SHM_SIZE 1024*1024
10 
11 int main()
12 {
13     const char *name = "/home/pathenon/project/network";
14     int i = 1;
15 
16     key_t key = ftok(name, i);
17     if(-1 == key)
18     {
19         perror("ftok");
20         return 1;
21     }
22 
23     int shm_id=shmget(key, MAX_SHM_SIZE, IPC_CREAT|0666);
24     if(-1 == shm_id)
25     {
26         perror("shmget");
27         return 1;
28     }
29 
30     char *p = (char *)shmat(shm_id, 0, 0);
31     if((void *)-1 == (void *)p)
32     {
33         perror("shmat");
34         return 1;
35     }
36 
37     //read memory
38     int size;
39     memcpy(&size, p, 4);
40     char buffer[1024] = {'\0'};
41     memcpy(buffer, p+4, size);
42 
43     printf("%s", buffer);
44 
45     shmdt(p);
46 
47     return 0;
48 }

分别编译上面两个程序,并先运行第一个可执行程序,后运行第二个,会发现输出:Hello share memory ipc     

 

   我们可以总结一下使用共享内存的大致步骤:

    1.使用ftok获得一个key_t值

    2.使用 shmget()开辟一块共享内存

    3.使用shmat()允许本进程使用某块共享内存

 

  4.对共享内存进行操作
  5.禁止本进程使用这块共享内存 shmdt()

    6.使用shmctl()或者命令行下ipcrm删除这块共享内存

     注意:在使用完共享内存后,如果没有在程序中用shmctl()删除共享内存就退出程序,一定要在命令行下用ipcrm命令删除这块共享内存否则它就一直在那儿放着。

     下面使用ipcs命令和ipcrm命令来查看与删除共享内存。

>ipcs -m

 

------ Shared Memory Segments --------

key        shmid      owner      perms      bytes      nattch     status

0x00000000 65538      yangfan    600        196608     2         

>ipcrm -m 65538

 

------ Shared Memory Segments --------

key        shmid      owner      perms      bytes      nattch     status

0x00000000 65538      yangfan    600        196608     2          dest

posted on 2012-07-17 20:32  pathenon  阅读(612)  评论(0编辑  收藏  举报

导航