面试题答案
一键面试设计方案
- 共享内存设置:使用
shmat
函数将共享内存段连接到进程地址空间,获取共享内存地址。 - 信号处理函数:定义信号处理函数,在信号处理函数中接收共享内存地址参数。
- 数据一致性与同步性:利用
semaphore
(信号量)来保证共享内存访问的同步性。信号量用于控制对共享内存的访问,确保在同一时间只有一个进程能够访问共享内存,从而保证数据一致性。
核心代码片段
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <signal.h>
#include <semaphore.h>
#define SHM_SIZE 1024
sem_t *sem;
// 共享内存结构体
typedef struct {
int data[100];
} SharedData;
// 信号处理函数
void signal_handler(int signum, siginfo_t *info, void *context) {
sem_wait(sem);
SharedData *shared_mem = (SharedData *)info->si_value.sival_ptr;
// 处理共享内存数据
for (int i = 0; i < 100; i++) {
printf("Received data: %d\n", shared_mem->data[i]);
}
sem_post(sem);
}
int main() {
key_t key = ftok(".", 'a');
if (key == -1) {
perror("ftok");
return 1;
}
int shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);
if (shmid == -1) {
perror("shmget");
return 1;
}
SharedData *shared_mem = (SharedData *)shmat(shmid, NULL, 0);
if (shared_mem == (void *)-1) {
perror("shmat");
return 1;
}
sem = sem_open("/semaphore", O_CREAT, 0666, 1);
if (sem == SEM_FAILED) {
perror("sem_open");
return 1;
}
struct sigaction sa;
sa.sa_sigaction = signal_handler;
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGUSR1, &sa, NULL) == -1) {
perror("sigaction");
return 1;
}
// 填充共享内存数据
for (int i = 0; i < 100; i++) {
shared_mem->data[i] = i;
}
union sigval sv;
sv.sival_ptr = shared_mem;
if (sigqueue(getppid(), SIGUSR1, sv) == -1) {
perror("sigqueue");
return 1;
}
// 等待信号处理完成
sleep(1);
if (shmdt(shared_mem) == -1) {
perror("shmdt");
return 1;
}
if (sem_close(sem) == -1) {
perror("sem_close");
return 1;
}
if (sem_unlink("/semaphore") == -1) {
perror("sem_unlink");
return 1;
}
if (shmctl(shmid, IPC_RMID, NULL) == -1) {
perror("shmctl");
return 1;
}
return 0;
}
这段代码实现了以下功能:
- 创建共享内存并填充数据。
- 定义信号处理函数
signal_handler
,通过SA_SIGINFO
标志在信号处理函数中传递共享内存地址。 - 使用信号量确保共享内存访问的同步性。
- 发送信号并等待信号处理完成,最后清理共享内存和信号量资源。