MST

星途 面试题库

面试题:C语言共享内存的同步机制问题

在Linux下使用C语言操作共享内存时,可能会出现多个进程同时访问共享内存导致数据不一致的情况。请阐述你所知道的用于解决该同步问题的方法,并且用C语言代码示例说明如何使用其中一种同步机制(如信号量)来保证共享内存数据的一致性。
33.9万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

解决同步问题的方法

  1. 信号量(Semaphore):信号量是一个计数器,用于控制对共享资源的访问。通过获取和释放信号量来控制进程对共享内存的访问,从而保证数据一致性。
  2. 互斥锁(Mutex):互斥锁本质上是一种特殊的二元信号量(值为0或1),用于保证在同一时刻只有一个进程能够访问共享资源。
  3. 条件变量(Condition Variable):条件变量通常与互斥锁一起使用,用于线程或进程间的同步。它允许进程在某个条件满足时被唤醒。
  4. 读写锁(Read - Write Lock):读写锁区分读操作和写操作。允许多个进程同时进行读操作,但只允许一个进程进行写操作,并且在写操作进行时不允许读操作。

使用信号量解决共享内存同步问题的C语言代码示例

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <semaphore.h>
#include <unistd.h>

#define SHM_SIZE 1024

int main() {
    key_t key;
    int shmid;
    char *shmaddr;
    sem_t *semaphore;

    // 生成一个唯一的键值
    key = ftok(".", 'a');
    if (key == -1) {
        perror("ftok");
        return 1;
    }

    // 创建共享内存段
    shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);
    if (shmid == -1) {
        perror("shmget");
        return 1;
    }

    // 连接共享内存段到进程地址空间
    shmaddr = (char *)shmat(shmid, NULL, 0);
    if (shmaddr == (void *)-1) {
        perror("shmat");
        return 1;
    }

    // 创建信号量
    semaphore = sem_open("/mysemaphore", O_CREAT, 0666, 1);
    if (semaphore == SEM_FAILED) {
        perror("sem_open");
        return 1;
    }

    // 子进程
    if (fork() == 0) {
        // 获取信号量
        if (sem_wait(semaphore) == -1) {
            perror("sem_wait");
            return 1;
        }

        // 子进程写入共享内存
        sprintf(shmaddr, "Hello from child process");
        printf("Child process has written to shared memory.\n");

        // 释放信号量
        if (sem_post(semaphore) == -1) {
            perror("sem_post");
            return 1;
        }
    } else {
        // 父进程等待子进程完成写入
        wait(NULL);

        // 获取信号量
        if (sem_wait(semaphore) == -1) {
            perror("sem_wait");
            return 1;
        }

        // 父进程读取共享内存
        printf("Parent process reads from shared memory: %s\n", shmaddr);

        // 释放信号量
        if (sem_post(semaphore) == -1) {
            perror("sem_post");
            return 1;
        }

        // 分离共享内存段
        if (shmdt(shmaddr) == -1) {
            perror("shmdt");
            return 1;
        }

        // 删除共享内存段
        if (shmctl(shmid, IPC_RMID, NULL) == -1) {
            perror("shmctl");
            return 1;
        }

        // 删除信号量
        if (sem_close(semaphore) == -1) {
            perror("sem_close");
            return 1;
        }
        if (sem_unlink("/mysemaphore") == -1) {
            perror("sem_unlink");
            return 1;
        }
    }

    return 0;
}

此代码展示了如何使用信号量来保证共享内存数据的一致性。在父子进程间,通过信号量来协调对共享内存的读写操作,避免数据不一致问题。