MST

星途 面试题库

面试题:C语言进程间通信之共享内存的同步问题

在使用共享内存进行进程间通信时,会面临同步问题。请描述一种在C语言环境下解决共享内存同步问题的方法,并编写一段简单的示例代码来展示该方法的应用。
47.6万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

解决方法

在C语言环境下,解决共享内存同步问题可以使用信号量(Semaphore)。信号量是一个整型变量,通过对其值的原子操作来实现同步。具体步骤如下:

  1. 创建信号量:使用semget函数创建一个信号量集。
  2. 初始化信号量:使用semctl函数对信号量进行初始化,设置其初始值。
  3. 获取信号量:使用semop函数获取信号量,如果信号量值为0,则进程会阻塞等待。
  4. 释放信号量:使用semop函数释放信号量,将信号量值加1,唤醒等待的进程。

示例代码

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

#define SHM_SIZE 1024

// 定义信号量操作结构
union semun {
    int val;
    struct semid_ds *buf;
    unsigned short *array;
};

int main() {
    key_t key;
    int shmid, semid;
    char *shmaddr;

    // 创建共享内存键值
    if ((key = ftok(".", 'a')) == -1) {
        perror("ftok");
        exit(1);
    }

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

    // 挂载共享内存
    if ((shmaddr = (char *)shmat(shmid, NULL, 0)) == (void *)-1) {
        perror("shmat");
        exit(1);
    }

    // 创建信号量键值
    if ((key = ftok(".", 'b')) == -1) {
        perror("ftok");
        exit(1);
    }

    // 创建信号量集
    if ((semid = semget(key, 1, IPC_CREAT | 0666)) == -1) {
        perror("semget");
        exit(1);
    }

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

    struct sembuf semopbuf;
    semopbuf.sem_num = 0;
    semopbuf.sem_op = -1;
    semopbuf.sem_flg = 0;

    // 获取信号量
    if (semop(semid, &semopbuf, 1) == -1) {
        perror("semop");
        exit(1);
    }

    // 使用共享内存
    sprintf(shmaddr, "Hello, shared memory!");
    printf("Process %d wrote: %s\n", getpid(), shmaddr);

    semopbuf.sem_op = 1;
    // 释放信号量
    if (semop(semid, &semopbuf, 1) == -1) {
        perror("semop");
        exit(1);
    }

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

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

    // 删除信号量
    if (semctl(semid, 0, IPC_RMID) == -1) {
        perror("semctl");
        exit(1);
    }

    return 0;
}

上述代码展示了在C语言中如何使用信号量解决共享内存的同步问题。代码创建了共享内存和信号量,通过获取和释放信号量来确保对共享内存的安全访问。