IPC
共享内存
共享内存区是可用IPC形式里面最快的。共享内存允许多个进程同时访问同一内存区,进程会将内存区映射到自己的地址空间中。这样进程间数据的传递不再涉及内核,减少了数据复制的动作。例如一个客户从服务器读的操作,使用管道消息队列等形式的话,需要内核将数据复制到进程空间的服务器上,然后服务器写到内核空间的IPC上。这样一次读取或者写入需要将数据复制两次。
使用共享内存
- 进程必须首先分配它
- 随后需要访问这个共享内存块的每一个进程都必须将这个共享内存绑定到自己的地址空间中
- 当完成通信之后,所有进程都将脱离共享内存,并且由一个进程释放该共享内存块
在/proc/sys/kernel/目录下,记录着共享内存的一些限制,如一个共享内存区的最大字节数shmmax,系统范围内最大共享内存区标识符数shmmni等,可以手工对其调整,但不推荐这样做。
共享内存的使用,主要有以下几个API:ftok()、shmget()、shmat()、shmdt()及shmctl()。
- 1
- 2
- 3
- 4
- 5
shmget():创建一个新的共享内存区,或者访问一个已经存在的内存区。
shmat():创建或者打开后,通过shmat把它连接到调用进程的地址空间。
shmdt():断开连接的内存区。当一个进程终止时,它所有链接的共享内存区都会自动断掉,注意这个函数并不删除共享内存区。
shmctl():提供对共享内存区的多种操作,例如删除。
出处:http://blog.csdn.net/caoli98033/article/details/44599273
在一个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下面的几种进程通讯方式。
- 管道:管道的名字挺形象的,就一个一个先进先出的队列,一个进程从一端读,另一个进程从另一端写,是一个环形缓冲区。管道有字节缓冲区,因此有大小限制。同时,管道分为命名管道(FIFO)和匿名管道。只有父子之间的经常才可以共享匿名管道,就是受fork限制,而命名管道可以在无亲缘关系的进程间使用,使用mififo函数创建,指定pathname作为路径名。
- 1
- 2
- 3
- 4
PS:创建后打开管道,必须读或者写,不能既读又写,属于半双工。
2. 消息队列:消息队列就像一个信箱,有人投递有人取。消息队列具有内核持续性,一个进程往某个队列写入一些消息,终止后,另一个进程可以读取。因此说是一个链表更为合适。注意发送者可以设置优先级,优先级最高的最早消息总是位于队列的头部。
3. 共享内存:共享内存是UNIX提供的进程通讯手段中最快的。前面已经介绍过了。注意一下需要自己提供同步的手段。
4.信号:信号和信号量看起来很像。信号是指signal,用于向一个进程通知发生异步事件的机制,而信号量是一种同步手段,就是PV原语那些东西。信号的传递是通过修改信号所发到的进程的某一个位域完成的。只有一位,无法排队。进程可以选择执行默认行为(如终止),执行一个信号处理函数或者忽略该信号。
简单看一下unix常用的信号:
注意前面32个是传统的unix信号,无法排队,因此可能造成信号的丢失。而后面32是可靠信息,可靠的意思是信息可以排队,信号不丢失。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
5.套接字:socket,上面介绍的通讯手段限制了作用域,套接字编程应用则更为广泛,可用于不同机器之间的通讯。网络的两端都建立一个socket对象,然后通过socket对象进行数据的传输。《unix网络编程卷一》对socket编程有详细的介绍。
静态链接库和动态链接库
堆和栈
堆和Heap管理有关, 默认存在系统堆和CRT堆. 具体大小取决于程序本身对内存的分配和使用, 可以调用HeapSize看实际使用大小.
另外还有虚拟内存, 独立于对堆外, 直接通过VirtualAlloc预留或分配. 也属于进程动态分配的内存.
而线程的栈空间大小在linux下可以使用ulimit -s查询,我的环境下默认是8192字节。windows下一说默认1M,一说2M。