- 浏览: 1341185 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
chinaxy1:
...
ON DUPLICATE KEY UPDATE重复插入时更新 -
b_l_east:
不一定哦,就算大小相当,in 和 exists的性能也会很大差 ...
mysql查询语句in和exists二者的区别和性能影响 -
llp1990311:
[size=x-small][/size]
如何正确防御xss攻击 -
home198979:
q315506754 写道还是佩服写c的 用其它语言一样可以实 ...
玩转深度优先搜索算法 -
q315506754:
还是佩服写c的
玩转深度优先搜索算法
shmget
int shmget(key_t key, size_t size, int flag);
key: 标识符的规则
size:共享存储段的字节数
flag:读写的权限
返回值:成功返回共享存储的id,失败返回-1
key_t key
-----------------------------------------------
key标识共享内存的键值: 0/IPC_PRIVATE。 当key的取值为IPC_PRIVATE,则函数shmget()将创建一块新的共享内存;如果key的取值为0,而参数shmflg中设置了IPC_PRIVATE这个标志,则同样将创建一块新的共享内存。
在IPC(InterProcess Communication)的通信模式下,不管是使用消息队列还是共享内存,甚至是信号量,每个IPC的对象(object)都有唯一的名字,称为“键”(key)。通过“键”,进程能够识别所用的对象。“键”与IPC对象的关系就如同文件名称之于文件,通过文件名,进程能够读写文件内的数据,甚至多个进程能够共用一个文件。而在IPC的通讯模式下,通过“键”的使用也使得一个IPC对象能为多个进程所共用。
Linux系统中的所有表示System V中IPC对象的数据结构都包括一个ipc_perm结构,其中包含有IPC对象的键值,该键用于查找System V中IPC对象的引用标识符。如果不使用“键”,进程将无法存取IPC对象,因为IPC对象并不存在于进程本身使用的内存中。
通常,都希望自己的程序能和其他的程序预先约定一个唯一的键值,但实际上并不是总可能的成行的,因为自己的程序无法为一块共享内存选择一个键值。因此,在此把key设为IPC_PRIVATE,这样,操作系统将忽略键,建立一个新的共享内存,指定一个键值,然后返回这块共享内存IPC标识符ID。而将这个新的共享内存的标识符ID告诉其他进程可以在建立共享内存后通过派生子进程,或写入文件或管道来实现。
int size(单位字节Byte)
-----------------------------------------------
size是要建立共享内存的长度。所有的内存分配操作都是以页为单位的。所以如果一段进程只申请一块只有一个字节的内存,内存也会分配整整一页(在i386机器中一页的缺省大小PACE_SIZE=4096字节)这样,新创建的共享内存的大小实际上是从size这个参数调整而来的页面大小。即如果size为1至4096,则实际申请到的共享内存大小为4K(一页);4097到8192,则实际申请到的共享内存大小为8K(两页),依此类推。
int shmflg
-----------------------------------------------
shmflg主要和一些标志有关。其中有效的包括IPC_CREAT和IPC_EXCL,它们的功能与open()的O_CREAT和O_EXCL相当。
IPC_CREAT 如果共享内存不存在,则创建一个共享内存,否则打开操作。
IPC_EXCL 只有在共享内存不存在的时候,新的共享内存才建立,否则就产生错误。
如果单独使用IPC_CREAT,shmget()函数要么返回一个已经存在的共享内存的操作符,要么返回一个新建的共享内存的标识符。如果将IPC_CREAT和IPC_EXCL标志一起使用,shmget()将返回一个新建的共享内存的标识符;如果该共享内存已存在,或者返回-1。IPC_EXEL标志本身并没有太大的意义,但是和IPC_CREAT标志一起使用可以用来保证所得的对象是新建的,而不是打开已有的对象。对于用户的读取和写入许可指定SHM_R和SHM_W,(SHM_R>3)和(SHM_W>3)是一组读取和写入许可,而(SHM_R>6)和(SHM_W>6)是全局读取和写入许可。
需要注意的是,使用参数要加上 | 0666 作为校验,在有些Linux系统中,如果不加此校验,则不能顺利获取共享空间的值(如Ubuntu)。此外,有两个常用参数,一般要同时出现,他们是:S_IRUSH | S_IWUSR 。由于这两个参数非常常用,程序员一般做这样的操作
#define PERM S_IRUSR | S_IWUSR | IPC_CREAT
这样一来,第三个参数就可以直接用PERM来表示了!
返回值
-----------------------------------------------
成功返回共享内存的标识符;不成功返回-1,errno储存错误原因。
EINVAL 参数size小于SHMMIN或大于SHMMAX。
EEXIST 预建立key所致的共享内存,但已经存在。
EIDRM 参数key所致的共享内存已经删除。
ENOSPC 超过了系统允许建立的共享内存的最大值(SHMALL )。
ENOENT 参数key所指的共享内存不存在,参数shmflg也未设IPC_CREAT位。
EACCES 没有权限。
ENOMEM 核心内存不足。
struct shmid_ds
-----------------------------------------------
shmid_ds数据结构表示每个新建的共享内存。当shmget()创建了一块新的共享内存后,返回一个可以用于引用该共享内存的shmid_ds数据结构的标识符。
include/linux/shm.h
struct shmid_ds {
struct ipc_perm shm_perm; /* operation perms */
int shm_segsz; /* size of segment (bytes) */
__kernel_time_t shm_atime; /* last attach time */
__kernel_time_t shm_dtime; /* last detach time */
__kernel_time_t shm_ctime; /* last change time */
__kernel_ipc_pid_t shm_cpid; /* pid of creator */
__kernel_ipc_pid_t shm_lpid; /* pid of last operator */
unsigned short shm_nattch; /* no. of current attaches */
unsigned short shm_unused; /* compatibility */
void *shm_unused2; /* ditto - used by DIPC */
void *shm_unused3; /* unused */
};
struct ipc_perm
-----------------------------------------------
对于每个IPC对象,系统共用一个struct ipc_perm的数据结构来存放权限信息,以确定一个ipc操作是否可以访问该IPC对象。
struct ipc_perm {
__kernel_key_t key;
__kernel_uid_t uid;
__kernel_gid_t gid;
__kernel_uid_t cuid;
__kernel_gid_t cgid;
__kernel_mode_t mode;
unsigned short seq;
};
//----------------------------------------
shmat
void *shmat(int shmid, const void *addr, int flag);
shmid:共享存储的id
addr:一般为0,表示连接到由内核选择的第一个可用地址上,否则,如果flag没有指定SHM_RND,则连接到addr所指定的地址上,如果flag为SHM_RND,则地址取整
flag:如前所述,一般为0
返回值:如果成功,返回共享存储段地址,出错返回-1
共享存储器的执行方式是将一个储存器区段标记为共用,这时各进程可以把这个区段映射到该进程本身的虚拟地址里。建立共享存储器可通过shmget系统调用,shmget执行后,核心程序就保留一块指定大小的空间,同时关于此共享存储器的一切数据,如区段的长度,区段的存取权,区段建立者的进程识别码等存入一个叫shmid_ds的结构。现在共享存储器虽然已经建立了,可是仍无法连上它,这时就须通过shmat系统调用得到一个指向共享存储器基址的指针,通过此指针,就可以如同于操作一般存储器似的取用共享存储器。shmdt进行相反的工作,用来脱离已连上的共享存储器。
shmdt
int shmdt(void *addr);
addr:共享存储段的地址,以前调用shmat时的返回值
shmdt将使相关shmid_ds结构中的shm_nattch计数器值减1
当一个进程不再需要共享内存段时,它将调用shmdt()系统调用取消这个段,但是,这并不是从内核真正地删除这个段,而是把相关shmid_ds结构的 shm_nattch域的值减1,当这个值为0时,内核才从物理上删除这个共享段
shmctl
int shmctl(int shmid,int cmd,struct shmid_ds *buf)
shmid:共享存储段的id
cmd:一些命令
IPC_STAT 得到共享内存的状态
IPC_SET 改变共享内存的状态
IPC_RMID 删除共享内存
IPC_RMID 命令实际上不从内核删除一个段,而是仅仅把这个段标记为删除,实际的删除发生在最后一个进程离开这个共享段时。
请注意,共享内存不会随着程序结束而自动消除,要么调用shmctl删除,要么自己用手敲命令去删除,否则永远留在系统中。
实例:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #define PERM S_IRUSR|S_IWUSR int main(int argc,char **argv){ int shmid; char *p_addr,*c_addr; if(argc!=2){ fprintf(stderr,"Usage:%s\n\a",argv[0]); exit(1); } if((shmid=shmget(IPC_PRIVATE,1024,PERM))==-1){ fprintf(stderr,"Create Share Memory Error:%s\n\a",strerror(errno)); exit(1); } if(fork()){ p_addr=shmat(shmid,0,0); memset(p_addr,'\0',1024); strncpy(p_addr,argv[1],1024); exit(0); }else{ c_addr=shmat(shmid,0,0); printf("Client get %s",c_addr); exit(0); } }这个程序是父进程将参数写入到共享内存,然后子进程把内容读出来.最后我们要使用ip
crm 释放资源的.先用ipcs 找出ID 然后用ipcrm shm ID 删除.
发表评论
-
【转载】如何用Linux的命令正确识别cpu的个数和核数
2013-08-20 11:40 1926如何在Linux下cpu的个数和核数呢?googel了一下 ... -
redis2.6.9源码学习---ziplist
2013-05-16 12:05 1803ziplist相比之前分析的z ... -
redis2.6.9源码学习---zipmap
2013-05-02 17:03 2261在看此文件源码之前,先看到此文件头部的英文注释,以下是本人 ... -
redis2.6.9源码学习---zipmap
2013-05-02 14:22 0<div class="iteye-blog- ... -
非阻塞connect编程
2013-04-08 17:08 1760非阻塞模式有3种用途 1.三次握手同时做其他的处理。co ... -
C库需要注意的函数
2013-03-08 16:50 2275本文转自:http://hub.opensolaris ... -
redis2.6.9源码学习---adlist
2013-02-07 16:27 1321源码adlist.c adlist.h,先来看看adlist ... -
redis2.6.9源码学习---dict
2013-02-07 11:59 1506redis的hashtable------dict.c ... -
redis2.6.9源码学习---Big_Endian&Little_Endian
2013-02-04 10:50 2778在阅读redis源码/src/endianconv.c时遇 ... -
linux c学习笔记----SCTP基础客户/服务编程(setsockopt,sctp_sendmsg等)
2013-01-15 17:53 19708在编程之前先了解一下sctp套接字选项 setsoc ... -
linux c学习笔记----UDP基础客户/服务编程(sendto,recvfrom)
2013-01-14 18:01 53780sendto(经socket传送数据) 相关函数 ... -
linux c学习笔记----select函数详解
2013-01-11 17:25 20364select系统调用是用来让我们的程序监视多个文件句柄(fil ... -
linux c学习笔记----TCP基础客户/服务编程(socket,bind等)
2013-01-10 17:29 28466socket(建立一个socket通信) 相关 ... -
linux c学习笔记----互斥锁属性
2013-01-05 18:37 11556互斥锁属性 使用互斥锁(互斥)可以使线程按顺序执行。通 ... -
linux c学习笔记----线程属性
2013-01-04 17:38 4623一.线程属性 线程具有属性,用pthre ... -
linux c学习笔记----线程同步
2012-12-28 17:49 30281.互斥量 互斥变量用pthead_mutex_t数据类 ... -
linux c学习笔记----线程创建与终止
2012-12-14 17:32 13732进程原语 线程原语 描述 fork p ... -
linux c学习笔记----消息队列(ftok,msgget,msgsnd,msgrcv,msgctl)
2012-12-07 17:46 33455ftok() #include <sys/t ... -
linux信号列表
2012-11-30 16:40 2873我们运行如下命令, ... -
linux c学习笔记----信号(sigaction,sigaddset,sigprocmask)
2012-11-30 16:23 15282sigaction(查询 ...
相关推荐
在 C 语言中,使用共享内存可以通过 shmget、shmat、shmdt 和 shmctl 函数来实现。 1. shmget 函数: shmget 函数用于开辟或使用一块共享内存。它的原型为 `int shmget(key_t key, int size, int shmflg)`,其中 `...
综上所述,使用C语言在Linux下实现共享内存通信涉及的关键点包括共享内存的创建、映射、解除映射以及控制,这些操作通过`shmget()`、`shmat()`、`shmdt()`和`shmctl()`函数完成。同时,需要注意进程间的同步问题以...
本文将详细介绍Linux环境下C语言编程中的几种进程通信方法,包括POSIX无名信号量、System V信号量、System V消息队列以及System V共享内存。 #### 1. POSIX无名信号量 ##### 理论基础 信号量是一种用于控制多个...
这是我剖的2.6.15版本的linux内核源码 共享内存部分源码 其中包括shmget shmmat shmdt shmctl函数的内核调用,以及内核创建共享内存的过程。
### Linux共享内存详解 #### 一、概述 在Linux及Unix环境下,进程间通信(IPC, Inter-Process Communication)是一项重要的技术,它允许不同进程之间交换数据和信息。System V IPC提供了三种通信机制:消息队列、...
### Linux通过共享内存实现进程之间的通信 #### 一、概述 共享内存作为一种高效的过程间通信(IPC)方式,允许多个进程直接访问同一段物理内存。这种方法的优势在于减少了数据复制的开销,使得进程间的数据交换更为...
### Linux共享内存实现进程间通信详解 #### 一、引言 在Linux系统中,进程间的通信(Inter-Process Communication, IPC)是一项重要的技术,它允许不同进程之间交换数据和同步执行。其中一种高效的进程间通信方法是...
### Linux共享内存浅析 #### 共享内存概述 共享内存是进程间通信(IPC)的一种方式,通过在内核中开辟一块特定的内存区域,允许多个进程对其进行访问,以此实现数据的共享和传递。相比其他进程间通信机制,共享...
在Linux中,可以使用`shmget`函数创建共享内存段,`shmat`函数将该段映射到进程的地址空间,而`shmdt`函数用于解除映射。另外,`shmctl`函数提供了对共享内存的高级控制,如删除或改变其属性。 在实际应用中,信号...
在C和C++中,实现共享内存主要依赖于系统提供的API,如在Unix/Linux系统中,我们通常使用`<sys/shm.h>`头文件中的函数,如`shmget`、`shmat`、`shmdt`和`shmctl`等。以下是一个简单的共享内存实现流程: 1. **创建...
在Linux中,可以使用`shmget`函数创建共享内存,`shmat`函数将共享内存附加到进程的地址空间,而`shmdt`用于解除对共享内存的附加。此外,`shmctl`用于管理共享内存段,例如删除或调整大小。 **信号量** 是一个整型...
【共享内存】是一种高效的数据通信方式,特别是在Linux和Unix系统中,它允许多个进程共享同一块内存区域,从而实现快速的数据交换。系统通过/proc/sys/kernel/目录下的配置文件(如shmmax和shmmni)来限制共享内存的...
内存共享的核心在于系统调用`shmget`、`shmat`、`shmdt`和`shmctl`,它们分别用于创建、映射、取消映射和控制共享内存段。下面,我们将详细讲解这些系统调用和相关的C代码实现。 1. `shmget`:创建共享内存段 `...
2. **Linux中的共享内存API** - `shmget()`:创建或获取一个共享内存段。返回一个标识符(key_t),用于后续操作。 - `shmat()`:将共享内存段映射到当前进程的地址空间。返回内存映射的地址。 - `shmdt()`:解除...
like系统(如Linux)中,共享内存主要通过`sys/shm.h`头文件中的函数来操作,比如`shmget`用于创建共享内存,`shmat`用于将共享内存附加到进程地址空间,`shmdt`用于解除共享内存的附加,以及`shmctl`用于控制共享...
在 `writeshm.c` 中,进程生成一个key,然后通过 `shmget()` 创建共享内存,再通过 `shmat()` 映射到进程的虚拟地址空间,写入数据后,通过 `shmdt()` 解除映射,并最终使用 `shmctl()` 销毁共享内存。在 `readshm.c...
### Linux共享内存概述 Linux中的共享内存是一种进程间通信(IPC)机制,允许两个或多个进程共享同一块内存区域。这种技术可以提高程序的性能,因为数据无需复制即可在不同进程之间共享。共享内存段可以由一个进程...
1. **System V IPC共享内存**:这是早期的Linux版本中常用的共享内存实现,通过`shmget`、`shmat`、`shmdt`和`shmctl`等系统调用来管理共享内存。`shmget`用于创建或获取共享内存,`shmat`将共享内存附加到进程的...
- **附着共享内存**:调用`shmat()`将共享内存段附加到进程的虚拟内存中。`shmat()`返回一个指针,指向共享内存段在进程地址空间中的起始位置。 - **使用共享内存**:此时,进程可以通过返回的指针来访问和修改...
下面我们将详细讲解如何在C语言中实现服务器(server.c)和客户端(client.c)的共享内存通信: **服务器端(server.c)** 1. 使用ftok()生成共享内存的关键字。 2. 调用shmget()创建共享内存段,设置适当的权限和...