一. 进程间通信
进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息。进程通信根据交换信息量的多少和效率的高低,分为低级通信(只能传递状态和整数值)和高级通信(提高信号通信的效率,传递大量数据,减轻程序编制的复杂度)。高级通信的三种主要方式为:共享内存模式、消息传递模式、共享文件模式。
这里主要介绍共享内存模式实现方法和简单例子。
二. 进程间共享内存
基本函数:
创建或打开共享存储区(shmget) | • 依据用户给出的整数值key,创建新区或打开现有区,返回一个共享存储区ID。 |
---|---|
连接共享存储区(shmat) | • 连接共享存储区到本进程的地址空间,可以指定虚拟地址或由系统分配,返回共享存储区首地址。父进程已连接的共享存储区可被fork创建的子进程继承。 |
拆除共享存储区连接(shmdt) | 拆除共享存储区与本进程地址空间的连接。 |
共享存储区控制(shmctl) | • 对共享存储区进行控制。如:共享存储区的删除需要显式调用shmctl(shmid, IPC_RMID, 0); |
创建共享存储区需要两个进程的IPC键值相同。
用系统调用ftok给出IPC键值key:保证同一个用户的两个进程获得相同IPC键值key,使用方法如下:
• ftok用于保证同一个用户的两个进程获得相同的IPC键值key;对于两个不同用户下的两组相同程序获得互不干扰的IPC键值。
• ftok的头文件:
• #include <sys/types.h>
• #include <sys/ipc.h>
• ftok原型如下:
• key_t ftok( char * fname, int id )
• 其中
• fname就是你指定的文件名(已经存在的文件名),一般使用当前目录,如:
• key_t key;
• key = ftok(".", 1); //这里就是将fname设为当前目录。
• id是子序号。
• 当删除重建文件后,ftok获得的key_t值会改变。
• 如果要确保key_t值不变,要么确保ftok的文件不被删除,要么不用ftok,指定一个固定的key_t值。
三. 进程共享内存的简单例子
通过进程间共享内存,在子进程中形成斐波那契数列,在父进程中输出。代码实现如下:
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdlib.h>
#include<errno.h>
#define SIZE 1024
extern int errno;
int main(){
int *fib;
int n;
int i=0;
scanf("%d",&n);
if(n<0)
printf("request a non-negative number!\n");
int shmid;
key_t key;
pid_t pid;
int* shmptr;
if((key = ftok(".", 1)) < 0){ #由ftok得到IPC键值
printf("ftok error!\n");
return -1;
}
if((shmid = shmget(key, SIZE,IPC_CREAT | 0660)) < 0){ #创建共享存储区
printf("shmget error!\n");
exit(-1);
}
shmptr = (int*)shmat(shmid, NULL, 0); #连接共享存储区
fib = shmptr; #斐波那契数组的指针指向共享存储区地址,即共享该数组空间
if(fib == (int*)(-1)){
printf("shmat error!\n");
exit(-1);
}
pid = fork();
if(pid<0){ #创建子进程失败
printf("fork error!\n");
return -1;
}
else if(pid==0){ #在子进程中
fib[0]=0;
fib[1]=1;
for(i=2;i<n;++i){ #计算斐波那契数列
fib[i]=fib[i-1]+fib[i-2];
}
if((shmctl(shmid, IPC_RMID, 0) < 0)){ #控制共享存储区
printf("shmctl error!\n");
exit(-1);
}
exit(0);
}
else{ #父进程
wait(0); #等待子进程结束
for(i=0;i<n;++i)
printf("%d ",fib[i]);
printf("\n");
if(shmdt(fib)==-1){
printf("shmdt error!\n");
exit(-1);
}
}
exit(0);
}