⑴ c/c++ unix c/linux c 嵌入式 共享内存
错误比较不明显,最要的错误是int shmid=shmget(key,4,IPC_CREAT|IPC_EXCL|0660);这一行之中的标志位IPC_EXCL确保创建新的唯一的共享内存,如果已经存在(也就是说之前使用了一次),他将返回错误,故将这个标志位去掉,其他的不是很严重,忽略的是没有最后删除共享内存,而只是分离了共享内存。修改代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/shm.h>
intmain()
{
key_tkey=ftok(".",100);
if(key==-1){
perror("ftok");
return-1;
}
intshmid=shmget(key,0,0);
if(shmid==-1)
{
perror("shmget");
exit(-1);
}
void*p=shmat(shmid,0,0);
if(p==(void*)-1)
{perror("shmat");
exit(-1);
}
int*pi=p;
printf("*pi=%d ",*pi);
shmdt(p);
}
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/shm.h>
intmain()
{
key_tkey=ftok(".",100);
if(key==-1){
perror("ftok");
return-1;
}
intshmid=shmget(key,4,IPC_CREAT|0660);
if(shmid==-1)
{
perror("shmget");
exit(-1);
}
void*p=shmat(shmid,0,0);
if(p==(void*)-1)
{perror("shmat");
exit(-1);
}
int*pi=p;
*pi=100;
shmdt(p);
}
⑵ linux查看共享内存命令
共享内存查看
使用ipcs命令,不加如何参数时,会把共享内存、信号量、消息队列的信息都打印出来,如果只想显示共享内存信息,使用如下命令:
[root@localhost ~]# ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 1867776 root 600 393216 2 dest
0x00000000 1900545 root 600 393216 2 dest
0x00030021 1703938 zc 666 131104 1
0x0003802e 1736707 zc 666 131104 1
0x00030004 1769476 zc 666 131104 1
0x00038002 1802245 zc 666 131104 1
0x00000000 1933318 root 600 393216 2 dest
0x00000000 1966087 root 600 393216 2 dest
0x00000000 1998856 root 600 393216 2 dest
0x00000000 2031625 root 600 393216 2 dest
0x00000000 2064394 root 600 393216 2 dest
0x0014350c 2261003 cs 666 33554432 2
0x00000000 2129932 root 600 393216 2 dest
0x00000000 2162701 root 600 393216 2 dest
0x00143511 395837454 root 666 1048576 1
其中:
第一列就是共享内存的key;
第二列是共享内存的编号shmid;
第三列就是创建的用户owner;
第四列就是权限perms;
第五列为创建的大小bytes;
第六列为连接到共享内存的进程数nattach;
第七列是共享内存的状态status。其中显示“dest”表示共享内存段已经被删除,但是还有用户在使用它,当该段内存的mode字段设置为SHM_DEST时就会显示“dest”。当用户调用shmctl的IPC_RMID时,内存先查看多少个进程与这个内存关联着,如果关联数为0,就会销毁这段共享内存,否者设置这段内存的mod的mode位为SHM_DEST,如果所有进程都不用则删除这段共享内存。
⑶ linux共享内存会不会被编译器优化
利用共享内存(Share Memory)可以让我们在任意两个进程之间传递数据,而且也是相对容易实现的一种方法,在正常情
况下,一个进程所使用的内存是不允许其它进程访问的,但是通过共享内存可以实现数据的共享。
使用共享内存用到的API函数有:
# include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
key_t ftok(const char *pathname, int proj_id)
其中pathname为当前进程的程序名,第二个参数为进程所开辟的第几个共享内存,返回一个key_t值,用于共享内存的获取
使用。
int shmget(key_t shmkey, int shmsiz, int flag)
void *shmat(int shmid, char *shmaddr, int shmflag)
int shmdt(char *shmaddr)
shmget是用来创建或者指向一块共享内存的函数,其中shmkey是共享内存的标识符,如果父子关系的进程间通信的话,这
个标识用IPC_PRIVATE替代,如果没有任何关系,可以使用ftok计算出来;Shmsiz是这块内存的大小;flag是这块内存的模
式和权限标识(IPC_CREAT, IPC_ALLOC, IPC_EXCL,0666权限)。函数成功返回共享内存的shmid,否则返回-1表示失败。
Shmat用来允许进程访问共享内存的函数,其中shmid是共享内存的ID,shmaddr是共享内存起始位置,shmflag是本进程对
内存操作模式,SHM_RDONLY是只读模式,成功返回共享内存的起始位置。
Shmdt与shmat相反,是用来禁止进程访问一块共享内存的函数。
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
其中shmid是共享内存的ID,cmd是控制命令(IPC_STAT, IPC_SET, IPC_RMID),struct shmid_ds *buf是一个结构体指针
,如果要改变共享内存的状态,使用它来指定,获得状态就存放在这个结构体中。
上述API函数的详细说明请使用man(男人)查看:
# man shmget | shmat | shmdt | shmctl
下面使用一个简单的例子说明如何使用共享内存。
// sharememcut.c 拷贝用户输入的字符串到共享内存中
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
int main()
{
key_t shmkey;
int shmid, in_tmp;
char *head, *pos, in_data[4096], *in_ptr;
// Create share memory KEY
shmkey = ftok("sharememcut", 1);
// Get the share memory ID
shmid = shmget(shmkey, sizeof(in_data), IPC_CREAT | 0666);
// Allow the process to access share memory, and get the address
head = pos = shmat(shmid, 0, 0);
in_ptr = in_data;
// Receive the character from stdin, 'q' to quit
while ((in_tmp = getchar()) != 'q') {
*in_ptr = in_tmp;
in_ptr++;
}
*in_ptr = '\0';
in_ptr = in_data;
// Cut the data into share memory
while (*in_ptr != '\0') {
*pos++ = *in_ptr++;
}
// Prohabit the process to access share memory
shmdt(head);
return 0;
}
# gcc -o sharememcut sharememcut.c 编译sharememcut.c
# ./sharememcut 执行sharememcut创建共享内存
…
# ipcs -m | grep 4096 查看创建的共享内存
0x01068288 348848145 root 666 4096 0
// sharemempaste.c 将共享内存的内容显示在屏幕上并且删除共享内存
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
int main()
{
key_t shmkey;
int shmid;
char *head, *pos, out_data[4096], *out_ptr;
// Create share memory KEY
shmkey = ftok("sharememcut", 1);
// Get the share memory ID
shmid = shmget(shmkey, sizeof(out_data), 0666);
if (shmid == -1)
return -1;
// Allow the process to access share memory, and get the address
head = pos = shmat(shmid, 0, 0);
out_ptr = out_data;
// Get the data from share memory
while (*pos != '\0') {
*out_ptr++ = *pos++;
}
*out_ptr = '\0';
// Output the data into stdout
printf("%s\n", out_data);
fflush(stdout);
// Prohabit the process to access share memory
shmdt(head);
// Delete the share memory
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
# gcc -o sharemempaste sharemempaste.c 编译sharemempaste.c
# ./sharemempaste 执行程序显示共享内存的内容
⑷ linux命令怎么删除共享内存
可以使用samba协议。Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服务器及客户端程序构成。SMB是一种在局域网上共享文件和打印机的一种通信协议,它为局域网内的不同计算机之间提供文件及打印机等资源的共享服务。
⑸ linux共享内存的控制释放
调用 shmctl(Shared Memory Control,控制共享内存)函数会返回一个共享内存块的相关信息。同时 shmctl 允许程序修改这些信息。该函数的第一个参数是一个共享内存块标识。
要获取一个共享内存块的相关信息,则为该函数传递 IPC_STAT 作为第二个参数,同时传递一个指向一个 struct shmid_ds 对象的指针作为第三个参数。
要删除一个共享内存块,则应将 IPC_RMID 作为第二个参数,而将 NULL 作为第三个参数。当最后一个绑定该共享内存块的进程与其脱离时,该共享内存块将被删除。
您应当在结束使用每个共享内存块的时候都使用 shmctl 进行释放,以防止超过系统所允许的共享内存块的总数限制。调用 exit 和 exec 会使进程脱离共享内存块,但不会删除这个内存块。 要查看其它有关共享内存块的操作的描述,请参考shmctl函数的手册页。
⑹ linux 共享内存 地址是唯一的吗
所谓共享内存就是使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。其他进程能把同一段共享内存段“连接到”他们自己的地址空间里去。所有进程都能访问共享内存中的地址。如果一个进程向这段共享内存写了数据,所做的改动会即时被有访问同一段共享内存的其他进程看到。共享内存的使用大大降低了在大规模数据处理过程中内存的消耗,但是共享内存的使用中有很多的陷阱,一不注意就很容易导致程序崩溃。
超过共享内存的大小限制?
在一个linux服务器上,共享内存的总体大小是有限制的,这个大小通过SHMMAX参数来定义(以字节为单位),您可以通过执行以下命令来确定 SHMMAX 的值:
# cat /proc/sys/kernel/shmmax
如果机器上创建的共享内存的总共大小超出了这个限制,在程序中使用标准错误perror可能会出现以下的信息:
unable to attach to shared memory
解决方法:
1、设置 SHMMAX
SHMMAX 的默认值是 32MB 。一般使用下列方法之一种将 SHMMAX 参数设为 2GB :
通过直接更改 /proc 文件系统,你不需重新启动机器就可以改变 SHMMAX 的默认设置。我使用的方法是将以下命令放入 />etc/rc.local 启动文件中:
# echo "2147483648" > /proc/sys/kernel/shmmax
您还可以使用 sysctl 命令来更改 SHMMAX 的值:
# sysctl -w kernel.shmmax=2147483648
最后,通过将该内核参数插入到 /etc/sysctl.conf 启动文件中,您可以使这种更改永久有效:
# echo "kernel.shmmax=2147483648" >> /etc/sysctl.conf
2、设置 SHMMNI
我们现在来看 SHMMNI 参数。这个内核参数用于设置系统范围内共享内存段的最大数量。该参数的默认值是 4096 。这一数值已经足够,通常不需要更改。
您可以通过执行以下命令来确定 SHMMNI 的值:
# cat /proc/sys/kernel/shmmni
4096
3、设置 SHMALL
最后,我们来看 SHMALL 共享内存内核参数。该参数控制着系统一次可以使用的共享内存总量(以页为单位)。简言之,该参数的值始终应该至少为:
ceil(SHMMAX/PAGE_SIZE)
SHMALL 的默认大小为 2097152 ,可以使用以下命令进行查询:
# cat /proc/sys/kernel/shmall
2097152
SHMALL 的默认设置对于我们来说应该足够使用。
注意: 在 i386 平台上 Red Hat Linux 的 页面大小 为 4096 字节。但是,您可以使用 bigpages ,它支持配置更大的内存页面尺寸。
⑺ linux 进程通信
nt shmget(key_t key, size_t size, int shmflg);
key_t key
-----------------------------------------------
key标识共享内存的键值: 0/IPC_PRIVATE。 当key的取值为IPC_PRIVATE,则函数shmget()将创建一块新的共享内存;如果key的取值为0,而参数shmflg中设置了IPC_PRIVATE这个标志,则同样将创建一块新的共享内存。
在IPC的通信模式下,不管是使用消息队列还是共享内存,甚至是信号量,每个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)是全局读取和写入许可。
返回值
-----------------------------------------------
成功返回共享内存的标识符;不成功返回-1,errno储存错误原因。
EINVAL 参数size小于SHMMIN或大于SHMMAX。
EEXIST 预建立key所致的共享内存,但已经存在。
EIDRM 参数key所致的共享内存已经删除。
ENOSPC 超过了系统允许建立的共享内存的最大值(SHMALL )。
ENOENT 参数key所指的共享内存不存在,参数shmflg也未设IPC_CREAT位。
EACCES 没有权限。
ENOMEM 核心内存不足。
⑻ 如何设置linux的共享内存
首先先使用shmget建立一块共享内存,然后向该内存中写入数据并返回该共享内存shmid
使用另一个程序通过上一程序返回的shmid读该共享内存内的数据
建立共享内存并写入数据的程序
#include<stdio.h>
#include<string.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdlib.h>
#include<errno.h>
voidget_buf(char*buf)
{
inti=0;
while((buf[i]=getchar())!=' '&&i<1024)
i++;
}
intmain(void)
{
intshmid;
shmid=shmget(IPC_PRIVATE,sizeof(char)*1024,IPC_CREAT|0666);
if(shmid==-1)
{
perror("shmget");
}
char*buf;
if((int)(buf=shmat(shmid,NULL,0))==-1)
{
perror("shmat");
exit(1);
}
get_buf(buf);
printf("%d ",shmid);
return0;
}
读取数据的程序
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdlib.h>
intmain(intargc,char**argv)
{
intshmid;
shmid=atoi(argv[1]);
char*buf;
if((int)(buf=shmat(shmid,NULL,0))==-1)
{
perror("shmat");
exit(1);
}
printf("%s ",buf);
shmdt(buf);
return0;
}
命令行的第一个参数设为第一个程序输出的数字
如
使用完以后可以使用
ipcrm -m 19562507
来删除该共享内存