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;成功返回其他值。

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

//process1.cc

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/ipc.h>

#define MAX_SHM_SIZE 1024*1024

int main(int argc, char *argv[])
{
    const char *name = "/home/pathenon/project/network";
    int i = 1;

    key_t key = ftok(name, i);
    if(-1 == key)
    {
        perror("ftok");
        return 1;
    }

    int shm_id=shmget(key, MAX_SHM_SIZE, IPC_CREAT|0666);
    if(-1 == shm_id)
    {
        perror("shmget");
        return 1;
    }

    char buffer[] = "Hello share memory ipc\n";
    char *p = (char *)shmat(shm_id, 0, 0);
    if((void *)-1 == (void *)p)
    {
        perror("shmat");
        return 1;
    }

    //write memory
    int size = sizeof(buffer);
    memcpy(p, &size, 4);
    memcpy(p+4, buffer, sizeof(buffer));

    shmdt(p);

    return 0;
}

//process2.cc

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/ipc.h>

#define MAX_SHM_SIZE 1024*1024

int main()
{
    const char *name = "/home/pathenon/project/network";
    int i = 1;

    key_t key = ftok(name, i);
    if(-1 == key)
    {
        perror("ftok");
        return 1;
    }

    int shm_id=shmget(key, MAX_SHM_SIZE, IPC_CREAT|0666);
    if(-1 == shm_id)
    {
        perror("shmget");
        return 1;
    }

    char *p = (char *)shmat(shm_id, 0, 0);
    if((void *)-1 == (void *)p)
    {
        perror("shmat");
        return 1;
    }

    //read memory
    int size;
    memcpy(&size, p, 4);
    char buffer[1024] = {'\0'};
    memcpy(buffer, p+4, size);

    printf("%s", buffer);

    shmdt(p);

    return 0;
}

   分别编译上面两个程序,并先运行第一个可执行程序,后运行第二个,会发现输出: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

转载于:https://my.oschina.net/pathenon/blog/64363

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用共享内存,应该有如下步骤: 1.开辟一块共享内存 shmget() 2.允许本进程使用共某块共享内存 shmat() 3.写入/读出 4.禁止本进程使用这块共享内存 shmdt() 5.删除这块共享内存 shmctl()或者命令行下ipcrm ftok()。它有两个参数,一个是字符串,一个是字符。字符串一般用当前进程的程序名,字符一般用来标记这个标识符所标识的共享内存是这个进程所开辟的第几个共享内存。ftok()会返回一个key_t型的值,也就是计算出来的标识符的值。 shmkey = ftok( "mcut" , 'a' ); // 计算标识符 操作共享内存,我们用到了下面的函数 #include #include #include int shmget( key_t shmkey , int shmsiz , int flag ); void *shmat( int shmid , char *shmaddr , int shmflag ); int shmdt( char *shmaddr ); shmget()是用来开辟/指向一块共享内存的函数。参数定义如下: key_t shmkey 是这块共享内存的标识符。如果是父子关系的进程间通信的话,这个标识符用IPC_PRIVATE来代替。但是刚才我们的两个进程没有任何关系,所以就用ftok()算出来一个标识符使用了。 int shmsiz 是这块内存的大小. int flag 是这块内存的模式(mode)以及权限标识。 模式可取如下值: 新建:IPC_CREAT 使用已开辟的内存:IPC_ALLOC 如果标识符以存在,则返回错误值:IPC_EXCL 然后将“模式” 和“权限标识”进行“或”运算,做为第三个参数。 如: IPC_CREAT | IPC_EXCL | 0666 这个函数成功时返回共享内存的ID,失败时返回-1。 // shmid开辟共享内存 shmid = shmget( shmkey , sizeof(in_data) , IPC_CREAT | 0666 ) ; shmat()是用来允许本进程访问一块共享内存的函数。 int shmid是那块共享内存的ID。 char *shmaddr是共享内存的起始地址 int shmflag是本进程对该内存的操作模式。如果是SHM_RDONLY的话,就是只读模式。其它的是读写模式 成功时,这个函数返回共享内存的起始地址。失败时返回-1。 char *head , *pos , head = pos = shmat( shmid , 0 , 0 ); // 允许本进程使用这块共享内存 shmdt()与shmat()相反,是用来禁止本进程访问一块共享内存的函数。 参数char *shmaddr是那块共享内存的起始地址。 成功时返回0。失败时返回-1。 shmdt( head ); // 禁止本进程使用这块内存 此外,还有一个用来控制共享内存的shmctl()函数如下: #include #include #include int shmctl( int shmid , int cmd , struct shmid_ds *buf ); int shmid是共享内存的ID。 int cmd是控制命令,可取值如下: IPC_STAT 得到共享内存的状态 IPC_SET 改变共享内存的状态 IPC_RMID 删除共享内存 struct shmid_ds *buf是一个结构体指针。IPC_STAT的时候,取得的状态放在这个结构体中。如果要改变共享内存的状态,用这个结构体指定。 返回值: 成功:0 失败:-1 shmctl(shmid,IPC_RMID,NULL); 刚才我们的mpaste.c程序中还可以加入这样几句。 struct shmid_ds buf; ... ... shmctl( shmid , IPC_STAT , &buf ); // 取得共享内存的状态 ... ... shmctl( shmid , IPC_RMID , &buf ); // 删除共享内存 注意:在使用共享内存,结束程序退出后。如果你没在程序中用shmctl()删除共享内存的话,一定要在命令行下用ipcrm命令删除这块共享内存。你要是不管的话,它就一直在那儿放着了。 简单解释一下ipcs命令和ipcrm命令。 取得ipc信息: ipcs [-m|-q|-s] -m 输出有关共享内存(shared memory)的信息 -q 输出有关信息队列(me

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值