MST

星途 面试题库

面试题:C++ 多进程环境下共享资源的同步与通信

假设你正在开发一个C++ 多进程应用程序,多个进程需要共享一块内存区域来交换数据。请阐述如何实现进程间的共享内存,以及如何处理同步问题以避免数据竞争。详细说明在这种场景下,你会使用哪些同步机制(如信号量、互斥锁等),并举例说明如何在代码中实现。
18.6万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

1. 实现进程间共享内存

在C++ 中,可以使用系统调用shmgetshmatshmdt来实现进程间共享内存。

  • shmget:用于创建或获取共享内存段。
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <iostream>

int main() {
    key_t key = ftok(".", 'a');
    if (key == -1) {
        perror("ftok");
        return 1;
    }

    int shmid = shmget(key, 1024, IPC_CREAT | 0666);
    if (shmid == -1) {
        perror("shmget");
        return 1;
    }
    // 后续操作...
    return 0;
}
  • shmat:将共享内存段连接到进程的地址空间。
// 接上面代码
char* sharedMemory = (char*)shmat(shmid, nullptr, 0);
if (sharedMemory == (void*)-1) {
    perror("shmat");
    return 1;
}
  • shmdt:将共享内存段从进程的地址空间分离。
// 接上面代码
if (shmdt(sharedMemory) == -1) {
    perror("shmdt");
    return 1;
}

2. 处理同步问题及同步机制

  • 信号量:信号量是一个整型计数器,用于控制对共享资源的访问。可以使用semgetsemopsemctl系统调用来操作信号量。
#include <sys/sem.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <iostream>

union semun {
    int val;
    struct semid_ds *buf;
    unsigned short *array;
    struct seminfo *__buf;
};

int main() {
    key_t key = ftok(".", 'b');
    if (key == -1) {
        perror("ftok");
        return 1;
    }

    int semid = semget(key, 1, IPC_CREAT | 0666);
    if (semid == -1) {
        perror("semget");
        return 1;
    }

    union semun sem_set;
    sem_set.val = 1; // 初始化信号量为1
    if (semctl(semid, 0, SETVAL, sem_set) == -1) {
        perror("semctl");
        return 1;
    }

    struct sembuf sem_op;
    sem_op.sem_num = 0;
    sem_op.sem_op = -1; // P操作,获取信号量
    sem_op.sem_flg = SEM_UNDO;
    if (semop(semid, &sem_op, 1) == -1) {
        perror("semop P");
        return 1;
    }

    // 访问共享内存

    sem_op.sem_op = 1; // V操作,释放信号量
    if (semop(semid, &sem_op, 1) == -1) {
        perror("semop V");
        return 1;
    }

    // 清理信号量
    if (semctl(semid, 0, IPC_RMID, 0) == -1) {
        perror("semctl IPC_RMID");
        return 1;
    }
    return 0;
}
  • 互斥锁:互斥锁本质上是特殊的二元信号量(值为0或1)。在POSIX系统中,可以使用pthread_mutex_t类型及相关函数。
#include <pthread.h>
#include <iostream>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void* threadFunction(void* arg) {
    if (pthread_mutex_lock(&mutex) != 0) {
        perror("pthread_mutex_lock");
        return nullptr;
    }

    // 访问共享内存

    if (pthread_mutex_unlock(&mutex) != 0) {
        perror("pthread_mutex_unlock");
        return nullptr;
    }
    return nullptr;
}

int main() {
    pthread_t thread;
    if (pthread_create(&thread, nullptr, threadFunction, nullptr) != 0) {
        perror("pthread_create");
        return 1;
    }

    if (pthread_join(thread, nullptr) != 0) {
        perror("pthread_join");
        return 1;
    }

    pthread_mutex_destroy(&mutex);
    return 0;
}

在多进程应用程序中,信号量更适合进程间同步,因为它是系统级别的同步机制。而互斥锁主要用于线程间同步,但如果使用pthread_mutexattr_setpshared设置互斥锁属性为进程间共享,也可用于进程间同步。