共享内存
来源:互联网 发布:日语扫描翻译软件 编辑:程序博客网 时间:2024/05/22 11:30
共享内存是系统出于多个进程之间通讯的考虑,而预留的的一块内存区。在/proc/sys/kernel/目录下,记录着共享内存的一些限制,如一个共享内存区的最大字节数shmmax,系统范围内最大共享内存区标识符数shmmni等,可以手工对其调整,但不推荐这样做。
共享内存的使用,主要有以下几个API:ftok()、shmget()、shmat()、shmdt()及shmctl()。
1)用ftok()函数获得一个ID号.应用说明:
在IPC中,我们经常用用key_t的值来创建或者打开信号量,共享内存和消息队列。
函数原型:
key_t ftok(const char *pathname, int proj_id);
Keys:
pathname一定要在系统中存在并且进程能够访问的
proj_id是一个1-255之间的一个整数值,典型的值是一个ASCII值。
当成功执行的时候,一个key_t值将会被返回,否则-1被返回。我们可以使用strerror(errno)来确定具体的错误信息。
考虑到应用系统可能在不同的主机上应用,可以直接定义一个key,而不用ftok获得:
#define IPCKEY 0x344378
2)shmget()用来开辟/指向一块共享内存的函数
应用说明:shmget()用来获得共享内存区域的ID,如果不存在指定的共享区域就创建相应的区域。
函数原型:
int shmget(key_t key, size_t size, int shmflg);
key_t key 是这块共享内存的标识符。如果是父子关系的进程间通信的话,这个标识符用IPC_PRIVATE来代替。如果两个进程没有任何关系,所以就用ftok()算出来一个标识符(或者自己定义一个)使用了。
int size 是这块内存的大小.
int flag 是这块内存的模式(mode)以及权限标识。
模式可取如下值:
IPC_CREAT 新建(如果已创建则返回目前共享内存的id)
IPC_EXCL 与IPC_CREAT结合使用,如果已创建则则返回错误
然后将“模式” 和“权限标识”进行“或”运算,做为第三个参数。
如: IPC_CREAT | IPC_EXCL | 0640
例子中的0666为权限标识,4/2/1 分别表示读/写/执行3种权限,第一个0是UID,第一个6(4+2)表示拥有者的权限,第二个4表示同组权限,第3个0表示他人的权限。
这个函数成功时返回共享内存的ID,失败时返回-1。
关于这个函数,要多说两句。
创建共享内存时,shmflg参数至少需要 IPC_CREAT | 权限标识,如果只有IPC_CREAT 则申请的地址都是k=0xffffffff,不能使用;
获取已创建的共享内存时,shmflg不要用IPC_CREAT(只能用创建共享内存时的权限标识,如0640),否则在某些情况下,比如用ipcrm删除共享内存后,用该函数并用IPC_CREAT参数获取一次共享内存(当然,获取失败),则即使再次创建共享内存也不能成功,此时必须更改key来重建共享内存。
3) shmat()将这个内存区映射到本进程的虚拟地址空间。
函数原型:void *shmat( int shmid , char *shmaddr , int shmflag );
shmat()是用来允许本进程访问一块共享内存的函数。
int shmid是那块共享内存的ID。
char *shmaddr是共享内存的起始地址,如果shmaddr为0,内核会把共享内存映像到调用进程的地址空间中选定位置;如果shmaddr不为0,内核会把共享内存映像到shmaddr指定的位置。所以一般把shmaddr设为0。
int shmflag是本进程对该内存的操作模式。如果是SHM_RDONLY的话,就是只读模式。其它的是读写模式
成功时,这个函数返回共享内存的起始地址。失败时返回-1。
4) shmdt()函数删除本进程对这块内存的使用,shmdt()与shmat()相反,是用来禁止本进程访问一块共享内存的函数。
函数原型:int shmdt( char *shmaddr );
参数char *shmaddr是那块共享内存的起始地址。
成功时返回0。失败时返回-1。
5) shmctl() 控制对这块共享内存的使用
函数原型: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
struct shmid_ds{
struct ipc_perm shm_perm;/* 操作权限*/
int shm_segsz; /*段的大小(以字节为单位)*/
time_t shm_atime; /*最后一个进程附加到该段的时间*/
time_t shm_dtime; /*最后一个进程离开该段的时间*/
time_t shm_ctime; /*最后一个进程修改该段的时间*/
unsigned short shm_cpid; /*创建该段进程的pid*/
unsigned short shm_lpid; /*在该段上操作的最后1个进程的pid*/
short shm_nattch; /*当前附加到该段的进程的个数*/
/*下面是私有的*/
unsigned short shm_npages; /*段的大小(以页为单位)*/
unsigned long *shm_pages; /*指向frames->SHMMAX的指针数组*/
struct vm_area_struct *attaches; /*对共享段的描述*/
};
#include <sys/ipc.h>#include <sys/shm.h>#include <string.h>#include <stdio.h>#include <stdlib.h>#define IPCKEY 0x366378typedef struct{ char agen[10]; unsigned char file_no;} st_setting;int main(int argc, char** argv){ int shm_id; key_t key; st_setting *p_setting; //首先检查共享内存是否存在,存在则先删除 shm_id = shmget(IPCKEY ,1028,0640); if(shm_id != -1) { p_setting = (st_setting*)shmat(shm_id,NULL,0); if ( p_setting != (void *)-1) { shmdt(p_setting); shmctl(shm_id,IPC_RMID,0) ; } } shm_id=shmget(IPCKEY,1028,0640|IPC_CREAT|IPC_EXCL); if(shm_id==-1) { printf("shmget error\n"); return -1; } //将这块共享内存区附加到自己的内存段 p_setting=(st_setting*)shmat(shm_id,NULL,0); strncpy(p_setting->agen,"jinyh",10); printf( "agen:%s\n",p_setting->agen ); p_setting->file_no = 1; printf( "file_no:%d\n",p_setting->file_no ); system("ipcs -m");//此时可看到有进程关联到共享内存的信息,nattch为1 //将这块共享内存区从自己的内存段删除出去 if(shmdt(p_setting) == -1) perror(" detach error "); system("ipcs -m");//此时可看到有进程关联到共享内存的信息,nattch为0 //删除共享内存 if (shmctl( shm_id , IPC_RMID , NULL ) == -1) perror(" delete error "); //exit(0);}
- 【共享内存】共享内存
- 共享内存
- 共享内存
- 共享内存
- 共享内存
- 共享内存
- 共享内存
- 共享内存
- 共享内存
- 共享内存
- 共享内存
- 共享内存
- 共享内存
- 共享内存
- 共享内存
- 共享内存
- 共享内存
- 共享内存
- 十大前端开发框架(上)
- 类(python)
- tensorflow(5)-辅助函数
- 认识 HTML 4.0
- VS2015 MATLAB混合编程之COM组件
- 共享内存
- 文章标题
- KindEditor编辑器使用
- CSdn测试
- PyTorch笔记5-save和load神经网络
- 作业帮-将json数组里面的每一个对象的value取出生成与之对应的二维数组
- 串口 SWD Jtag
- 约瑟夫环(约瑟夫问题) 采用循环单链表实现
- [ARC066F]Contest with Drinks Hard