面试题答案
一键面试IPC方式选择与优化
- 选择共享内存:在高并发多进程服务器频繁数据传输场景下,共享内存是最佳选择之一。因为共享内存直接在内存中开辟共享区域,多个进程可以直接访问,无需像管道和消息队列那样进行数据的拷贝,从而大大提高数据传输效率,降低延迟。
- 优化措施:
- 同步机制:由于多个进程同时访问共享内存,需要引入同步机制,如信号量。信号量可以控制对共享内存的访问,避免竞争条件。
- 内存管理:合理规划共享内存的大小和布局,避免内存碎片。在使用完共享内存后,及时释放资源。
C语言代码示例
以下是使用共享内存和信号量实现进程间通信的关键代码示例:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <unistd.h>
// 信号量操作函数
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
};
void semaphore_p(int semid) {
struct sembuf sem_op;
sem_op.sem_num = 0;
sem_op.sem_op = -1;
sem_op.sem_flg = SEM_UNDO;
semop(semid, &sem_op, 1);
}
void semaphore_v(int semid) {
struct sembuf sem_op;
sem_op.sem_num = 0;
sem_op.sem_op = 1;
sem_op.sem_flg = SEM_UNDO;
semop(semid, &sem_op, 1);
}
int main() {
key_t key;
int shmid, semid;
int *shared_mem;
// 生成唯一的键值
key = ftok(".", 'a');
if (key == -1) {
perror("ftok");
return 1;
}
// 创建共享内存
shmid = shmget(key, sizeof(int), IPC_CREAT | 0666);
if (shmid == -1) {
perror("shmget");
return 1;
}
// 映射共享内存到进程地址空间
shared_mem = (int *)shmat(shmid, NULL, 0);
if (shared_mem == (void *)-1) {
perror("shmat");
return 1;
}
// 创建信号量
semid = semget(key, 1, IPC_CREAT | 0666);
if (semid == -1) {
perror("semget");
return 1;
}
// 初始化信号量
union semun sem_union;
sem_union.val = 1;
if (semctl(semid, 0, SETVAL, sem_union) == -1) {
perror("semctl");
return 1;
}
pid_t pid = fork();
if (pid == -1) {
perror("fork");
return 1;
} else if (pid == 0) {
// 子进程
semaphore_p(semid);
(*shared_mem) = 42;
semaphore_v(semid);
shmdt(shared_mem);
} else {
// 父进程
semaphore_p(semid);
printf("Value read from shared memory: %d\n", *shared_mem);
semaphore_v(semid);
shmdt(shared_mem);
shmctl(shmid, IPC_RMID, NULL);
semctl(semid, 0, IPC_RMID, 0);
}
return 0;
}
上述代码展示了如何使用共享内存和信号量在父子进程间进行数据传递。父进程和子进程通过共享内存来交换数据,利用信号量来同步对共享内存的访问。