Linux IPC_之共享内存

有关函数

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

    原型:int shmget(key_t key,size_t size,int shmflg);

    返回值:失败返回-1,成功返回标识

    参 数: key:一般由系统调用fotk获得,为0(IPC_PRIVATE)时会建立新共享内存对象

    size:要创建或得到的共享内存对象的大小,以字节为单位,和页(4k)对齐

    shmflg :

    0      取共享内存标识符,若不存在则函数会报错

    IPC_CREAT    如果内核中不存在键值与key相等的共享内存,则新建一个共享内                     存;如果存在这样的共享内存,返回此共享内存的标识符

    IPC_CREAT|IPC_EXCL   如果内核中不存在键值与key相等的共享内存,则新建                           一个消息队列;如果存在这样的共享内存则报错

    =========================================================================

  2. shmat  连接共享内存标识符为shmid的共享内存,链接成功后把共享内存区地址映射到进程地        址空间,随后该进程可以像访问本地空间一样来访问这块内存

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

    返回值:失败返回-1,成功返回shmid所标识的共享内存的映射到虚拟地址空间的地址

    参 数:shmid:共享内存的标识

    shmaddr:指定共享内存出现在进程内存地址的什么位置,直接指定为NULL时内核自己决定一          个合适的地址位置

    shmflg:

    SHM_RDONLY:只读模式

    其它:读写模式

    =========================================================================

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

    原型:int shmdt(const void*shmaddr);

    返回值:失败返回-1,成功返回0

    参数:shmaddr:shmat()的返回值(共享内存区地址映射到进程的地址)

    =========================================================================

  4. shmctl  对共享内存的管理与控制

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

    返回值:失败返回-1,成功返回0

    参数:shmid:共享内存的标识

    cmd:

    IPC_RMID:删除这片共享内存

    IPC_STAT:得到共享内存的状态,并复制到第三个参数buf所指向的结构体中

    IPC_SET:改变共享内存的状态,把buf所指向的结构体中的uid、gid、mode复制到共享内             存的shmid_ds结构中

    buf:共享内存管理结构体

    struct shmid_ds {

struct ipc_perm shm_perm;    /* Ownership and permissions */

size_t     shm_segsz;   /* Size of segment (bytes) */

time_t     shm_atime;   /* Last attach time */

time_t     shm_dtime;   /* Last detach time */

time_t     shm_ctime;   /* Last change time */

pid_t      shm_cpid;    /* PID of creator */

pid_t      shm_lpid;    /* PID of last shmat(2)/shmdt(2) */

shmatt_t    shm_nattch;  /* No. of current attaches */                       ...

};

  =========================================================================

代码实现:

shm.h

#ifndef _SHM_H_
#define _SHM_H_

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

#define __PATH__ "."
#define __PROJ_ID__ 0x26
#define SIZE 4096

int creat_shm(int _size);
int get_shm(int _size);
int destory_shm(int _shm_id);

#endif

shm.c

#include"shm.h"

static int comm_shm(int _size,int flags)
{
    key_t _key=-1;
    if((_key=ftok(__PATH__,__PROJ_ID__))<0){
        perror("ftok");
        return -1;
    }
    int _shm_id=-1;
    if((_shm_id=shmget(_key,_size,flags))<0){
        perror("shmget");
        return -1;
    }
    return _shm_id;
}

int creat_shm(int _size)
{
    return comm_shm(_size,IPC_CREAT|IPC_EXCL|0666);
}
int get_shm(int _size)
{
    return comm_shm(_size,IPC_CREAT);
}

int destory_shm(int _shm_id)
{
    if(shmctl(_shm_id,IPC_RMID,NULL)<0){
        perror("shmctl");
        return -1;
    }
    return 0;
}

shm_server.c

#include"shm.h"

int main()
{
    int _shm_id=creat_shm(SIZE);
    char *addr=(char*)shmat(_shm_id,0,0);
    sleep(5);
    int j=0;
    while(1){
        while(j<128){
            printf("%c  ",addr[j++]);
        }
        printf("\n");
        break;
    }   
    sleep(8);
    if(shmdt(addr)<0){
        perror("attach is failed!\n");
    }
    printf("attach has success!\n");

    sleep(3);
    destory_shm(_shm_id);
    printf("destory successed\n");

    return 0;
}

shm_client.c

#include"shm.h"

int main()
{
    int _shm_id=get_shm(SIZE);
    sleep(2);
    char *addr=(char*)shmat(_shm_id,0,0);

    int i=0;
    while(i<128){
        addr[i++]=i;
    }   
    sleep(10);
    if(shmdt(addr)<0){
        perror("attach is failed!\n");
    }   
    printf("attach has success!\n");
    return 0;
}

Makefile

.PHONY:all
all:shm_server shm_client
shm_server:shm_server.c shm.c 
    gcc -o [email protected] $^
shm_client:shm_client.c shm.c
    gcc -o [email protected] $^

.PHONY:clean
clean:
    rm -rf shm_server shm_client

运行server端结果:

运行client端结果:

运行前系统中所有的共享内存段(因为我们只关注它的变化,因此后面的截图只截了一部分)

运行中:  可以看到系统中多了shmid为1048590的Shared Memory,它的nattch为1

shmid为1048590的Shared Memory,它的nattch增加为2

shmid为1048590的Shared Memory,它的nattch减少为1

shmid为1048590的Shared Memory,它的nattch减少为0

shmid为1048590的Shared Memory,不存在了


时间: 2024-08-29 04:27:33

Linux IPC_之共享内存的相关文章

Linux IPC之共享内存C 事例

Linux IPC之共享内存 标签: linuxrandomnull工作 2011-08-25 11:52 4123人阅读 评论(0) 收藏 举报  分类: Linux(3)  读书札记(3)  版权声明:本文为博主原创文章,未经博主允许不得转载. 简介 共享内存(shared memory)是最简单的Linux进程间通信方式之一.使用共享内存,不同进程可以对同一块内存进行读写.由于所有进程对共享内存的访问就和访问自己的内存空间一样,而不需要进行额外系统调用或内核操作,同时还避免了多余的内存拷贝

Linux进程间通信—使用共享内存

Linux进程间通信-使用共享内存 转自: https://blog.csdn.net/ljianhui/article/details/10253345 下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像

Linux进程间通信——使用共享内存

下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样.而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程. 特别提醒:共

Linux进程间通信--mmap共享内存(一)

共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进程A可以即时看到进程B对共享内存中数据的更新,反之亦然.由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以. 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝.对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据[1]:一次从输入

Linux进程间通信--mmap()共享内存(二)

内核怎样保证各个进程寻址到同一个共享内存区域的内存页面 1.page cache及swap cache中页面的区分:一个被访问文件的物理页面都驻留在page cache或swap cache中,一个页面的所有信息由struct page来描述.struct page中有一个域为指针mapping ,它指向一个struct address_space类型结构.page cache或swap cache中的所有页面就是根据address_space结构以及一个偏移量来区分的. 2.文件与addres

Linux进程间通信--shmget()共享内存(二)

共享内存区域是被多个进程共享的一部分物理内存.如果多个进程都把该内存区域映射到自己的虚拟地址空间,则这些进程就都可以直接访问该共享内存区域,从而可以通过该区域进行通信.共享内存是进程间共享数据的一种最快的方法,一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容.这块共享虚拟内存的页面,出现在每一个共享该页面的进程的页表中.但是它不需要在所有进程的虚拟内存中都有相同的虚拟地址. 图 共享内存映射图 象所有的 System V IPC对象一样,对于共享内存对象的获取

unix/linux下的共享内存、信号量、队列信息管理

在unix/linux下,经常有因为共享内存.信号量,队列等共享信息没有干净地清楚而引起一些问题.查看共享信息的内存的命令是ipcs [-m|-s|-q]. 默认会列出共享内存.信号量,队列信息,-m列出共享内存,-s列出共享信号量,-q列出共享队列清除命令是ipcrm [-m|-s|-q] id.-m 删除共享内存,-s删除共享信号量,-q删除共享队列.

Linux编程之共享内存

Linux 支持两种方式的共享内存:System V 和 POSIX 共享内存. 1. POSIX 共享内存 1.1 POSIX 共享内存的由来 System V 共享内存和共享文件映射的不足: System V 共享内存模型使用的是键和标识符,这与标准的 UNIX I/O 模型使用文件名和描述符的做法是不一致的.这种差异意味着使用 System V 共享内存需要一整套全新的系统调用和命令. 使用一个共享文件映射来进行 IPC 要求创建一个磁盘文件,即使无需对共享区域进行持久存储也需要这样做.除

Linux 进程间共享内存 SYSTEMV

#include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, int size, int shmflag) key取值为IPC_PRIVATE时,shmflag应为IPC_CREAT,则新建共享内存key取值不为IPC_PRIVATE则应为已创建的key值,shmflag不应包含IPC_CREAT和IPC_EXCL,且大小小于等于原共享内存大小成功则返回共享内存id,失败返回-1 void *shmat(int sh