进程间通信
1内存共享
1.1 内存共享是最简单最快的通信方法,因为多个进程共同拥有一块内存,避免了系统调用和不必要的数据拷贝,
由于内核没有对内存共享做同步处理,所以同步我门要自己做,比如,一个内存块在没写入东西之前,不能被读, 两个进程不能同时访问一块内存。我门一般使用semaphores来解决这个问题。
1.2 内存模式
要使用共享内存,进程必须分配到内存片。要访问内存进程必须连上这个片,完了再释放掉。
在linux下,每个进程的虚拟内存都是被分成页的。每个进程都维护着一张地址表用来指向自己的内存的(存放真正数据
的地方)。当多个进程的地址表里都有同一个内存片的地址时,那这块内存片就为共享的内存了。
当分配一块新的共享内存时,会开辟一个新的虚拟内存页,所以只需一个进程来开辟一个新的共享内存,其他的进程
要用一块已经存在的内存,只需要在自己的内存表里加上一个到虚拟内存的映射,在使用完后,再释放掉。当没有
进程要用虚拟内存了,要释放掉虚拟内存。
1.3 内存分配
进程调用shmget("SHared Memory GET")来分配内存。第一个参数是内存标志,如果使用IPC_PRIVATE则可避免重名;第二个参数getpagesize(),每页的大小,因为
在linux下内存是以页为单位的。
第三个参数 IPC_CREAT | IPC_EXCL|S_IRUSR | S_IWUSR(IPC_CREAT,代表建立一个新的内存快,如果以存在描述的块,
则访问, S_IRUSR,代表共享内存所有者读,S_IWUSR,代表共享内存所有者写,S_IROTH and S_IWOTH 代表
所有的进程都可写可读;IPC_EXCL,这个标志要跟在 IPC_CREAT后用,如果建立的内存已经存在则出错,有它
的意思是,一定要建立一个新的内存。
int segment_id = shmget (shm_key, getpagesize (), IPC_CREAT | S_IRUSR | S_IWUSER);
如果调用成功就反回一个标志,如果存在该内存则,检测数据是否已损坏。
例子:
#include <stdio.h>
#include <sys/shm.h>
#include <sys/stat.h>
int main ()
{
int segment_id;
char* shared_memory;
struct shmid_ds shmbuffer; //关于共享内存的一些数据
int segment_size;
const int shared_segment_size = 0x6400;
/* Allocate a shared memory segment. */
segment_id = shmget (IPC_PRIVATE, shared_segment_size,
IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
/* Attach the shared memory segment. */
shared_memory = (char*) shmat (segment_id, 0, 0); //连接共享内存,第二个参数为空代表系统会利用一个可用地址来指向共享内存
printf ("shared memory attached at address %p/n", shared_memory);
/* Determine the segment's size. */
shmctl (segment_id, IPC_STAT, &shmbuffer); //得到共享内存的信息
segment_size =shmbuffer.shm_segsz;
printf ("segment size: %d/n", segment_size);
/* Write a string to the shared memory segment. */
sprintf (shared_memory, "Hello, world.");
/* Detach the shared memory segment. */
shmdt (shared_memory);
/* Reattach the shared memory segment, at a different address. */
shared_memory = (char*) shmat (segment_id, (void*) 0x5000000, 0); //指定一个地址来连接共享内存
printf ("shared memory reattached at address %p/n", shared_memory);
/* Print out the string from shared memory. */
printf ("%s/n", shared_memory);
/* Detach the shared memory segment. */
shmdt (shared_memory);
/* Deallocate the shared memory segment. */
shmctl (segment_id, IPC_RMID, 0); //removeid干掉共享内存。
return 0;
}
调试::查看正在使用的共享内存
% ipcs -m
------ Shared Memory Segments -------
key shmid owner perms bytes nattch status
0x00000000 1627649 user 640 25600 0
----------------------------------------------------------------------------------------------------