面试题答案
一键面试实现思路
- 创建共享内存段:使用
shmget
函数创建共享内存段,该函数需要传入一个键值(可以通过ftok
函数生成)、共享内存大小以及权限标志。例如:
key_t key = ftok(".", 'a');
int shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);
- 将共享内存段附加到进程地址空间:通过
shmat
函数将创建好的共享内存段附加到当前进程的地址空间,得到一个指向共享内存的指针。
void *shmaddr = shmat(shmid, NULL, 0);
- 数据交换:两个进程都将共享内存段附加到自己的地址空间后,就可以通过这个共享内存区域进行数据交换。一个进程写入数据,另一个进程读取数据。
- 分离共享内存段:使用完共享内存后,通过
shmdt
函数将共享内存段从进程地址空间分离。
shmdt(shmaddr);
- 删除共享内存段:最后,使用
shmctl
函数删除共享内存段。
shmctl(shmid, IPC_RMID, NULL);
可能遇到的问题及解决方法
- 同步问题:两个进程对共享内存的访问可能会出现竞争条件,导致数据不一致。
- 解决方法:可以使用信号量(如
semget
、semop
等函数)来实现进程间的同步。例如,创建一个二元信号量,在访问共享内存前获取信号量,访问完成后释放信号量。
- 解决方法:可以使用信号量(如
- 内存溢出:如果写入共享内存的数据量超过了共享内存的大小,会导致内存溢出错误。
- 解决方法:在写入数据前,先检查共享内存剩余空间是否足够,或者在设计共享内存大小时充分考虑可能写入的数据量。
- 共享内存权限问题:如果权限设置不当,可能导致进程无法访问共享内存。
- 解决方法:在创建共享内存时,合理设置权限标志,确保相关进程具有足够的访问权限。
关键代码片段
以下是一个简单的示例代码,展示了如何使用共享内存进行进程间通信。
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#define SHM_SIZE 1024
int main() {
key_t key = ftok(".", 'a');
int shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);
if (shmid == -1) {
perror("shmget");
exit(1);
}
void *shmaddr = shmat(shmid, NULL, 0);
if (shmaddr == (void *)-1) {
perror("shmat");
exit(1);
}
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(1);
} else if (pid == 0) { // 子进程
char *message = "Hello from child!";
sprintf((char *)shmaddr, "%s", message);
shmdt(shmaddr);
} else { // 父进程
wait(NULL);
printf("Parent received: %s\n", (char *)shmaddr);
shmdt(shmaddr);
shmctl(shmid, IPC_RMID, NULL);
}
return 0;
}
这个示例代码创建了一个共享内存段,然后通过 fork
创建一个子进程。子进程向共享内存写入一条消息,父进程等待子进程完成后读取该消息。最后,父进程删除共享内存段。