zoukankan      html  css  js  c++  java
  • 16、XSI 共享内存简介

    1、共享内存

    1)分类

    XSI 共享内存

    匿名共享内存mmap

    2)原理:

    地址空间:一个连续的内存地址单元

    物理地址空间:物理内存地址组成的地址空间,其空间大小与物理内存一致。

    虚拟地址空间:CPU MMU 提供的功能,可将虚地址转换为物理地址,所有的虚地址组成的连续空间叫虚地址空间,有时候也叫线性空间。其空间大小与机器字长相关。32位机器上为2^324G左右

    wps_clip_image-3735

    3)特性:

        内核相关的;需要与同步原语一起使用才能保证数据一致性(Mutex,读写锁、信号量);最快速,copy较少

    4)API

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

    得到一个共享内存标识符或创建一个共享内存对象并返回共享内存标识符

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

    连接共享内存标识符为shmid的共享内存,连接成功后把共享内存区对象映射到调用进程的地址空间,随后可像本地空间一样访问

    int  shmdt(const void*  shmaddr); 

    shmat函数相反,是用来断开与共享内存附加点的地址,禁止本进程访问此片共享内存

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

    完成对共享内存的控制

    5)示例代码

    示例1:父子进程通信

    View Code
    #include <stdio.h>
    #include
    <unistd.h>
    #include
    <string.h>
    #include
    <sys/ipc.h>
    #include
    <sys/shm.h>
    #include
    <error.h>
    #define SIZE 1024

    int main()
    {
    int shmid;
    char *shmaddr;
    struct shmid_ds buf;
    int flag = 0;
    int pid;
    shmid
    = shmget(IPC_PRIVATE, SIZE, IPC_CREAT|0600);
    if (shmid < 0)
    {
    perror(
    "get shm ipc_id error");
    return -1;
    }
    pid
    = fork();
    if(pid == 0)
    {
    //child
    shmaddr = (char*)shmat(shmid, NULL, 0);
    if ((int)shmaddr == -1)
    {
    perror(
    "shmat addr error");
    return -1;
    }
    strcpy(shmaddr,
    "Hi, I am child process!\n");
    shmdt(shmaddr);
    return 0;
    }
    else if (pid > 0)
    {
    //parent
    sleep(3);
    flag
    = shmctl(shmid, IPC_STAT, &buf);
    if (flag == -1)
    {
    perror(
    "shmctl shm error");
    return -1 ;
    }
    printf(
    "shm_segsz =%d bytes\n", buf.shm_segsz);
    printf(
    "parent pid=%d, shm_cpid = %d \n", getpid(), buf.shm_cpid); //p_pid
    printf("chlid pid=%d, shm_lpid = %d \n", pid ,buf.shm_lpid); //c_pid
    shmaddr = (char *)shmat(shmid, NULL, 0);
    if ((int)shmaddr == -1)
    {
    perror(
    "shmat addr error") ;
    return -1 ;
    }
    printf(
    "%s", shmaddr);
    shmdt(shmaddr );
    shmctl(shmid, IPC_RMID, NULL);
    }
    else
    {
    perror(
    "fork error") ;
    shmctl(shmid, IPC_RMID, NULL);
    }
    return 0 ;
    }

    示例2:多进程读写,一个读,一个写

    shm_w
    #include <stdio.h>
    #include
    <sys/ipc.h>
    #include
    <sys/shm.h>
    #include
    <sys/types.h>
    #include
    <unistd.h>
    #include
    <string.h>

    typedef
    struct
    {
    char name[8];
    int age;
    } people;

    int main(int argc, char** argv)
    {
    int shm_id, i;
    key_t key;
    char temp[8];
    memset(temp,
    0, 8);
    people
    *p_map;
    char pathname[30];
    memset(pathname,
    0, 30);
    strcpy(pathname,
    "/tmp");
    key
    = ftok(pathname, 0x03);

    if(key == -1)
    {
    perror(
    "ftok error");
    return -1;
    }
    printf(
    "key = %d\n", key) ;
    shm_id
    = shmget(key, 4096, IPC_CREAT | IPC_EXCL | 0600);
    if(shm_id ==- 1)
    {
    perror(
    "shmget error");
    return -1;
    }
    printf(
    "shm_id = %d\n", shm_id) ;
    p_map
    =(people*)shmat(shm_id, NULL, 0);
    memset(temp,
    0x00, sizeof(temp));
    strcpy(temp,
    "test") ;
    temp[
    4] = '0';
    for(i = 0; i < 3; i++)
    {
    temp[
    4] += 1;
    strncpy((p_map
    +i)->name, temp, 5);
    (p_map
    +i)->age =0 + i;
    }
    shmdt(p_map);
    return 0 ;
    }

    shm_r
    #include <stdio.h>
    #include
    <string.h>
    #include
    <sys/ipc.h>
    #include
    <sys/shm.h>
    #include
    <sys/types.h>
    #include
    <unistd.h>

    typedef
    struct
    {
    char name[8];
    int age;
    } people;

    int main(int argc, char** argv)
    {
    int shm_id, i;
    key_t key;
    people
    *p_map;
    char pathname[30];
    memset(pathname,
    0, 30);
    strcpy(pathname,
    "/tmp") ;
    key
    = ftok(pathname, 0x03);

    if(key == -1)
    {
    perror(
    "ftok error");
    return -1;
    }

    printf(
    "key= %d\n", key) ;
    shm_id
    = shmget(key, 0, 0); //obatain the exist shm
    if(shm_id == -1)
    {
    perror(
    "shmget error");
    return -1;
    }
    printf(
    "shm_id= %d\n", shm_id) ;
    p_map
    = (people*)shmat(shm_id, NULL, 0);
    for(i = 0; i < 3; i++)
    {
    printf(
    "name: %s\n",(*(p_map+i)).name );
    printf(
    "age: %d\n",(*(p_map+i)).age );
    }
    if(shmdt(p_map) == -1)
    {
    perror(
    "detach error");
    return -1;
    }
    return 0 ;
    }

    使用ipcrm -m shm_id删除此共享内存

    参考

    1http://www.cnblogs.com/mydomain/archive/2011/06/23/2088339.html

    2http://blog.csdn.net/guoping16/article/details/6584058

    3http://linux.die.net/man/2/shmctl

  • 相关阅读:
    19、spring注解学习(声明式事务)——spring注解版声明式事务
    Visual C# 2015调用SnmpSharpNet库实现简单的SNMP元素查询
    SNMP协议交互学习-获取udp的udpindatagrams
    LwIP的SNMP学习笔记
    stm32f407使用Keil uV5建立工程日志
    IP unnumbered interface,某个接口不编号,某个接口不分配IP地址
    OSPFv3与OSPFv2协议的比较
    卫星网络-拓扑优化-文献笔记
    卫星轨道相关笔记SGP4
    [20190226]删除tab$记录的恢复6.txt
  • 原文地址:https://www.cnblogs.com/mydomain/p/2175351.html
Copyright © 2011-2022 走看看