System V 共享内存

一.共享内存数据结构


对于每个共享内存区,内核维护如下信息结构,定义在<sys/shm.h>, 在ubuntu中路径:/usr/include/linux/shm.h





二. System V共享内存函数:

#include <sys/ipc.h>
#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);    
void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
;


(1)
功能:用来创建共享内存
原型 int shmget(key_t key, size_t size,
int shmflg);

参数:
     key: 这个共享内存段名字

     size: 共享内存大小

     shmflg: 由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的


返回值:    成功返回一个非负整数,即该共享内存段的标识码;
        失败返回-1

(2)
功能:将共享内存段连接到进程地址空间
原型
void *shmat(int shmid, const void *shmaddr, int shmflg);
参数
    shmid:   共享内存标识
    shmaddr: 指定连接的地址
    shmflg:  它的两个可能取值是SHM_RND和SHM_RDONLY
返回值:成功返回一个指针,指向共享内存第一个字节;失败返回-1

  shmaddr 为NULL,内核自动选择一个地址
  shmaddr 不为NULL且shmflg无SHM_RND标记,则以shmaddr为连接地址。
  shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会自动向下调整为SHMLBA的整数倍。
            公式:shmaddr - (shmaddr % SHMLBA)    # SHMLBA为4096
 shmflg=SHM_RDONLY,表示连接操作用来只读共享内存


(3)
功能:将共享内存段与当前进程脱离
原型 int shmdt(const void *shmaddr);
参数
    shmaddr: 由shmat所返回的指针
    返回值:成功返回0;失败返回-1
注意:将共享内存段与当前进程脱离不等于删除共享内存段

(4)
功能:用于控制共享内存
原型 int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数
    shmid: 由shmget返回的共享内存标识码
    cmd:   将要采取的动作(有三个可取值)
    buf:    指向一个保存着共享内存的模式状态和访问权限的数据结构
返回值:成功返回0;失败返回-1

cmd 的取值如下,与消息队列类似:
    IPC_STAT 把shmid_ds结构中的数据设置为共享内存的当前关联值
    IPC_SET   在进程有足够权限的前提下,把共享内存的当前关联值设置为shmid_ds数据结构中给出的值

    IPC_RMID 删除共享内存段

shmwrite.c

#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/types.h>
#include<unistd.h>
#include<errno.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/mman.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<string.h>

#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

typedef struct stu
{
    char name[32];
    int age;
} STU;

int main(int argc, char *argv[])
{
    int shmid;
    shmid = shmget(1234,sizeof(STU),IPC_CREAT | 0666); //用来创建共享内存
    if(shmid == -1)
    	ERR_EXIT("shmget err");
    STU *p;
    p = shmat(shmid,NULL,0);//将共享内存段连接到进程地址空间
    if(p == (void*)-1)  //error (void *) -1 is returned
    	ERR_EXIT("shmat err");
    strcpy(p->name,"list");
    p->age = 20;
    while(1)  // 等待,接收内存中有quit字符串时,代表读取完成
    {
    	if(memcmp(p,"quit",4) == 0)// 需要注意的是,这里比较的是内存
    		break;
    }
    //sleep(10);
    shmdt(p);//将共享内存段与当前进程脱离
    shmctl(shmid,IPC_RMID,NULL);
    return 0;
}


shmread.c

#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/types.h>
#include<unistd.h>
#include<errno.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/mman.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<string.h>

#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

typedef struct stu
{
    char name[32];
    int age;
} STU;

int main(int argc, char *argv[])
{
    int shmid;
    shmid = shmget(1234,0,0); //用来创建共享内存
    if(shmid == -1)
    	ERR_EXIT("shmget err");
    STU *p;
    p = shmat(shmid,NULL,0);//将共享内存段连接到进程地址空间
    if(p == (void*)-1)  //error (void *) -1 is returned
    	ERR_EXIT("shmat err");
   
   	printf("name=%s  age=%d\n",p->name,p->age);
    
    memcpy(p,"quit",4);  // 读取完数据后,向内存中写入4个字节的数据,代表读取完成
    shmdt(p);//将共享内存段与当前进程脱离
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值