进程间的通信
众所周知,进程间的通信有多种,其中一种就是共享空间的使用
相关函数
在linux环境下进行进程间共享空间的操作,需要以下几个函数
创建或打开共享存储区(shmget)
- 依据用户给出的整数值key,创建新区或打开现有区
- 返回一个共享存储区ID。
连接共享存储区(shmat)
- 连接共享存储区到本进程的地址空间
- 返回共享存储区首地址
- 父进程已连接的共享存储区可被fork创建的子进程继承。
拆除共享存储区连接(shmdt)
- 拆除共享存储区与本进程地址空间的连接。
共享存储区控制(shmctl)
- 对共享存储区进行控制。
- 如:共享存储区的删除需要显式调用shmctl(shmid, IPC_RMID, 0);
用系统调用ftok给出IPC键值key
- 保证同一个用户的两个进程获得相同的IPC键值key
实验题目
- 在子进程创建Fibonacci序列,并存储在共享空间钟
- 在父进程访问共享空间,并输出子进程创建的序列
实践内容
- 代码如下
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/stat.h>
#define MAX_SIZE 10
struct fibonacci
{
int fib_seq[MAX_SIZE];
int size;
};
int main(int argc, char*argv[])
{
int f0 = 0, f1 = 1, f2 = 0;
if(argc != 2) {
fprintf(stderr, "Please input:the name of the program and a num\n");
fprintf(stderr, "eg:./a.out 5\n");
exit(0);
}
if(atoi(argv[1]) > 10) {
fprintf(stderr, "the num is too large");
exit(0);
}
if(atoi(argv[1]) < 2) {
fprintf(stderr, "the num is too small");
exit(0);
}
key_t kid;
kid = shmget(IPC_PRIVATE, MAX_SIZE, S_IRUSR|S_IWUSR);
struct fibonacci* fib = (struct fibonacci*)shmat(kid, NULL, 0);
fib->size = atoi(argv[1]);
//fib->size = 5;
pid_t pid = fork();
if(pid < 0) {
fprintf(stderr, "cteate child failed");
}
else if(pid == 0) {
fib->fib_seq[0] = f0;
fib->fib_seq[1] = f1;
for(int i = 2; i < fib->size; i++) {
f2 = f0 + f1;
f0 = f1;
f1 = f2;
fib->fib_seq[i] = f2;
}
printf("the child process is complete\n");
exit(0);
}
else {
wait(NULL);
for(int i = 0; i < fib->size; i++) {
printf("%d ", fib->fib_seq[i]);
}
printf("\nfinish!\n");
}
shmctl(kid, IPC_RMID, NULL);
return 0;
}
- 实验截图
- 实验思路
利用上面的函数,现在父进程钟创建一个共享空间,在父进程创建一个子进程,此时该子进程继承了父进程的共享空间。之后父进程等待子进程创建序列,创建完成后结束子进程,父进程访问共享空间进行读取输出即可。
实验难点
- 感觉其实共享空间的使用并不难,有个坑就是在于运行程序时,参数的输入。
- 一直以为输入的参数是存在argv[0]中,其实是储存在argv[1]中