IPC之共享内存
在多进程程序中(vfork创建的多进程除外),即使是全局变量也无法共享,各个进程都会保存局部变量或全局变量的副本,供自己使用。
共享内存将文件地址映射到内存中即可让多个进程共享内存中的数据。
内存映射API
#include<sys/mman.h>
void *mmp(void *addr, size_t len, int prot, int flags, int fd, off_t offset);//调用成功则返回被映射区的起始地址,出错则为MAP_FAILED
addr可以指定描述符fd应被映射到的进程内空间的起始地址。它通常被指定为一个空指针,这样告诉内核自己去选择起始地址。无论那种情况,该函数的返回值都是描述符fd所映射到内存区的起始地址。
使用例程
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/mman.h>
#include<fcntl.h>
#include<semaphore.h>
#define SEM_NAME "mysem"
int main(int argc, char *argv[])
{
int fd, i, nloop, zero = 0;
int *ptr;
sem_t *mutex;
if(argc != 3)
printf("usage :incr2 <pathname> <#loops>\n");
nloop = atoi(argv[2]);
fd = open(argv[1], O_RDWR|O_CREAT, 0664);
write(fd, &zero, sizeof(int));
ptr = mmap(NULL, sizeof(int), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
mutex = sem_open(SEM_NAME, O_CREAT|O_EXCL, 0664, 1);
sem_unlink(SEM_NAME);
setbuf(stdout, NULL);
if(fork() == 0)
{
for(i=0; i<nloop; ++i)
{
sem_wait(mutex);//对信号量mutex减一,是一个阻塞的原子操作
printf("child: %d\n", (*ptr)++);
sem_post(mutex);//对信号量mutex加一,是一个阻塞的原子操作
}
exit(0);
}
for(i=0; i<nloop; ++i)
{
sem_wait(mutex);
printf("parent %d\n", (*ptr)++);
sem_post(mutex);
}
exit(0);
}
sem_unlink功能简介
当进程创建一个有名信号量,会在/dev/shm下生成一个sem.xxx的文件,所有打开该信号量的进程(包括创建它的进程)都会增加该文件的引用计数,并且这个计数由内核管理。当调用sem_unlink时,/dev/shm下的sem.xxx文件会马上被删除,但是信号量本身并没有被删除,所有已打开该信号量的进程仍能正常使用它。直到所有打开该信号量的进程关闭该信号量后,内核才真正删除信号量。
运行一下
运行效果可以看出,进程在交替运行时,自增时使用的是一个变量。
不积小流无以成江河