面试题答案
一键面试1. 信号量原理
信号量是一个整型变量,通过一个计数器来控制对共享资源的访问。当计数器大于0时,进程可以获取信号量(计数器减1),从而访问共享资源;当计数器为0时,进程需要等待,直到其他进程释放信号量(计数器加1)。
2. 实现步骤
- 初始化信号量:在父进程中创建并初始化信号量,设置初始值为1(表示共享资源初始可用)。
- 创建子进程:父进程通过
fork
创建多个子进程,每个子进程都可以获取到信号量。 - 获取信号量:在子进程处理涉及共享数据的请求前,先获取信号量,若信号量不可用则等待。
- 访问共享数据:获取信号量后,进程可以安全地对共享数据进行读写操作。
- 释放信号量:完成对共享数据的操作后,释放信号量,使其他进程可以获取。
3. 关键代码示例(以C语言为例)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/wait.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 = ftok(".", 'a');
if (key == -1) {
perror("ftok");
exit(1);
}
// 创建信号量
int semid = semget(key, 1, IPC_CREAT | 0666);
if (semid == -1) {
perror("semget");
exit(1);
}
// 初始化信号量
union semun sem_set;
sem_set.val = 1;
if (semctl(semid, 0, SETVAL, sem_set) == -1) {
perror("semctl");
exit(1);
}
// 创建子进程
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(1);
} else if (pid == 0) {
// 子进程
semaphore_p(semid);
// 处理共享数据的请求
printf("Child process accessing shared data\n");
semaphore_v(semid);
exit(0);
} else {
// 父进程
wait(NULL);
// 删除信号量
if (semctl(semid, 0, IPC_RMID) == -1) {
perror("semctl");
exit(1);
}
}
return 0;
}
4. 总结
通过上述步骤和代码示例,我们可以使用信号量在基于多进程的网络服务器编程中实现进程间的同步,确保共享数据的一致性。在实际应用中,根据具体需求,可能需要更复杂的信号量操作和错误处理机制。