SHMGET

http://man7.org/linux/man-pages/man2/shmget.2.html

名称

shmget---分配一个system V 共享内存段

摘要

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

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

描述

shmget --- 分配一个system V共享内存段

声明

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

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

描述

shmget() 返回了参数key的值关联的system V 共享内存段的标识符。它可能用于获取之前已经创建的共享内存段的标识符(当shmflg是0, 且 key的值不是IPC_PRIVATE), 也可能是创建一个新的段。

一个新的共享内存段,它的的size 等于参数size对齐到PAGE_SIZE的整数倍;如果key的值是 IPC_PRIVATE,则会创建该新的的共享内存段; 如果key的值不是 IPC_PRIVATE, 但是该参数key没有对应的共享内存段且shmflg中设置了IPC_CREAT,则创建新的共享内存段。

如果shmflg 同时指定IPC_CREAT 和 IPC_EXCL ,并且该key的共享内存段已经存在,则  shmget() 会返回失败,errno 为 EEXIST。它仿照了open的 O_CREAT | O_EXCL 选项。

shmflg的值可以是如下所示的组合:

  •  IPC_CREAT  创建一个新的段。如果这个flag没有使用,shmget()会查找key对应的共享内存段,并且检查用户是否有访问该内存段的权限。
  • IPC_EXCL   这个flag 与IPC_CREAT配合使用, 来确保这个调用会创建一个共享内存段。如果该内存段已经存在,则调用失败。
  • SHM_HUGETLB (since Linux 2.6)  使用“huge pages” 分配一个共享内存段。详细信息见linux内核源文件Documentation/admin-guide/mm/hugetlbpage.rst
  •  SHM_HUGE_2MB, SHM_HUGE_1GB  (since Linux 3.8)    与SHM_HUGETLB配合使用来选择 可选择的hugetlb page size(相应的是2MB 或 1GB),如果系统支持“multiple hugetlb page sizes”。 通常, “desired huge page size” 可以配置成“desired page size”的对数,使用 SHM_HUGE_SHIFT偏移6个bit 。因此,上面的两个常数定义如下:

                           #define SHM_HUGE_2MB    (21 << SHM_HUGE_SHIFT)
                           #define SHM_HUGE_1GB    (30 << SHM_HUGE_SHIFT)

                       其它的信息可以查看mmap函数操作。

  • SHM_NORESERVE (since Linux 2.6.15)  这个flag与mmap的MAP_NORESERVE flag相同的作用,不要为该内存段保留swap space。当保留swap space, 其中一个用户要保证它可能修改了内存段。当没有保留swap space, 在没有可用内存时, 一个用户可以获取SIGSEGV错误号。 可以在“proc”的/proc/sys/vm/overcommit_memory文件中查看。

除了上面的flags, shmflg的最小的9个bits 指定了owner、group和others的权限。这些bits有相同的格式, 相同的含义,它们与open操作的mode参数一致。当前,执行权限没有被使用。

当一个新的共享内存段被创建,它的内容被初始化为0值,并且它相关联的结构提数据,hmid_ds
       (see shmctl(2)),按如下的方式进行初始化。

  • shm_perm.cuid 和 shm_perm.uid 被设置成调用进行的有效用户ID。
  • shm_perm.cgid 和 shm_perm.gid  被设置成调用进程的有效 groupID。
  • shm_perm.mode的最小的9个bits 被设置成shmflg的最小的9个bits。
  • shm_segsz 被设置成 size的值。
  • shm_lpid, shm_nattch, shm_atime, and shm_dtime 被设置为0
  • shm_ctime 被设置成当前时间。

如果共享内存段已经存在, 如果它标识为销毁, 会检查权限。

 

返回值

  • 如果成功,会返回一个合法的共享内存段标识符。如果出错,会返回-1, errno 来标识出错的原因。

ERRORS       如果出错,errno会被如下出错码的其中一个:

  • EACCES  用户没有访问共享内存段的权限,在管理它的IPC名字空间的用户名字空间内,它没有 CAP_IPC_OWNER 能力。
  •   EEXIST   在shmflg中指定了IPC_CREAT 和 IPC_EXCL,但是该key对应的共享内存段已经存在。
  • EINVAL  一个给定的key的内存段已经存在,但是它的size 大于已经存在的共享内存段。
  • ENFILE   系统级的限制, 限制打开文件的个数是否超过了限制。
  • ENOENT  给定的key不存在共享内存段, 并且没有指定IPC_CREAT。
  • ENOMEM 没有足够大的内存来分配共享内存段。
  • ENOSPC  所有可能的共享内存ID(SHMMNI)已经被使用,或者如果分配入参指定的size的内存段会引起超过系统级的共享内存的限制(SHMALL)。
  • EPERM  指定了SHM_HUGETLB, 但是调用者没有这个权限(没有 CAP_IPC_LOCK的权限)。

遵循的协议

  • POSIX.1-2001, POSIX.1-2008, SVr4.
  • SHM_HUGETLB and SHM_NORESERVE are Linux extensions.

说明:

共享内存的限制:如下共享内存段资源的限制会影响到shmget()的调用:

  • SHMALL  System-wide limit on the total amount of shared memory, measured in units of the system page size.在linux 中,这个限制可以通过对 /proc/sys/kernel/shmall 读取和修改来获取或修改。从linux 3.16,该属性的默认值为:

                      ULONG_MAX - 2^24

                 该值的作用是对内存分配不做限制。

  • SHMMAX   Maximum size in bytes for a shared memory segment.在linux, 这个限制可以通过读取或修改/proc/sys/kernel/shmmax 文件来获取。从linux 3.16 该值默认为:

                      ULONG_MAX - 2^24

                 该值的作用是对内存的分配没有限制。

  • SHMMIN  Minimum size in bytes for a shared memory segment: implementation dependent (currently 1 byte, though PAGE_SIZE  is the effective minimum size, 也就是说,虽然设置为1个byte, 实际上分配了一个PAGE_SIZE大小的内存)。在linux系统中该值通过 /proc/sys/kernel/shmmni读取或修改。

调用举例

https://www.cnblogs.com/fangshenghui/p/4039720.html

shmdata.h文件:

#ifndef _SHMDATA_H_HEADER
#define _SHMDATA_H_HEADER
#define TEXT_SZ 2048

struct shared_use_st
{
    int written;/*flag , 0: write available; not 0: read availbe;*/
    char text[TEXT_SZ];/*the data*/
};
#endif

 

shmread.c文件,共享内存读取;

#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<sys/shm.h>
#include"shmdata.h"

#define MEM_KEY (1234)

int main()
{
    int running =1; //judge if or not process is running
    void*shm = NULL; //the addres of share memory segment 
    struct shared_use_st *shared;//point to shm
    int shmid; //share memory id
    //create share memory

    shmid = shmget((key_t)MEM_KEY,sizeof(struct shared_use_st),0666|IPC_CREAT);
    if(shmid ==-1)
    {
        fprintf(stderr,"shmget failed\n");
        exit(EXIT_FAILURE);
    }
    //attach shared memory to current process namespace
    shm = shmat(shmid,0,0);
    if(shm ==(void*)-1)
    {
        fprintf(stderr,"shmat failed\n");
        exit(EXIT_FAILURE);
    }
    printf("\nMemory attached at %X\n",(int)shm);
    //convert user defined structure data;
    shared =(struct shared_use_st*)shm;
    shared->written =0;
    while(running)//read share memory data
    {
        //judge if or not this memory can read, other words, if not write process push data into the memory
        if(shared->written !=0)
        {
            printf("You wrote: %s", shared->text);
            sleep(rand()%3);
            //after reading the data, set written flag is 0 for next writting
            shared->written =0;
            //if writing data is 'end', exit reading cycle process
            if(strncmp(shared->text,"end",3)==0)
                running =0;
        }

        else//if no data input sleeping
            sleep(1);
    }
    //dis-attach the shared memory from current process
    if(shmdt(shm)==-1)
    {
        fprintf(stderr,"shmdt failed\n");
        exit(EXIT_FAILURE);
    }
    //delete the share memory
    if(shmctl(shmid, IPC_RMID,0)==-1)
    {
        fprintf(stderr,"shmctl(IPC_RMID) failed\n");
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}

 

 shwrite.c 文件---共享内存写入

#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<sys/shm.h>
#include"shmdata.h"
#define MEM_KEY (1234)

int main()
{
    int running =1;
    void*shm = NULL;
    struct shared_use_st *shared = NULL;
    char buffer[BUFSIZ +1];//used to save txt
    int shmid;
    //creat share memory segment 
    shmid = shmget((key_t)MEM_KEY,sizeof(struct shared_use_st),0666|IPC_CREAT);
    if(shmid ==-1)
    {
        fprintf(stderr,"shmget failed\n");
        exit(EXIT_FAILURE);
    }
    //associate the share memory to current process namespace
    shm = shmat(shmid,(void*)0,0);
    if(shm ==(void*)-1)
    {
        fprintf(stderr,"shmat failed\n");
        exit(EXIT_FAILURE);
    }
    printf("Memory attached at %X\n",(int)shm);
    //convert to our own structure obj
    shared =(struct shared_use_st*)shm;
    while(running)//write data to shared memory segment
    {
        //if data not read, waiting for reading , and do not write txt to this share memory
        while(shared->written ==1)
        {
            sleep(1);
            printf("Waiting...\n");
        }
        //write data to share memory segment 
        printf("Enter some text: ");
        fgets(buffer, BUFSIZ, stdin);
        strncpy(shared->text, buffer, TEXT_SZ);
        //if written is done, set the written flag as reading available
        shared->written =1;
        //input end, if we finish inputing the data, and exit the cycle , and exit the process
        if(strncmp(buffer,"end",3)==0)
            running =0;
    }
    //disattach the share memory from current process
    if(shmdt(shm)==-1)
    {
        fprintf(stderr,"shmdt failed\n");
        exit(EXIT_FAILURE);
    }
    sleep(2);
    exit(EXIT_SUCCESS);
}
      

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值