Linux 信号量:父子进程同步实现及 CPU 资源抢夺防止

在多进程编程中,父子进程可能会因为争抢 CPU 资源而导致程序运行出现问题。为了解决这个问题,可以使用 Linux 系统中的信号量机制来实现进程同步。本文将通过一个实例演示如何使用信号量函数来实现父子进程的同步,并防止他们抢夺 CPU 资源。

代码示例

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

#define SEM_KEY 1234

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

int main(int argc, char **argv) {
    int sem_id, pid, i;
    union semun sem_arg;
    struct sembuf sem_op;

    // 创建一个信号量集合
    sem_id = semget(SEM_KEY, 1, IPC_CREAT | 0666);
    if (sem_id == -1) {
        perror("semget");
        exit(EXIT_FAILURE);
    }

    // 初始化信号量为1,表示父进程先执行
    sem_arg.val = 1;
    if (semctl(sem_id, 0, SETVAL, sem_arg) == -1) {
        perror("semctl");
        exit(EXIT_FAILURE);
    }

    // 创建子进程
    pid = fork();
    if (pid == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    if (pid == 0) {  // 子进程
        for (i = 0; i < 5; i++) {
            // 等待信号量为1,表示轮到自己执行
            sem_op.sem_num = 0;
            sem_op.sem_op = -1;
            sem_op.sem_flg = 0;
            if (semop(sem_id, &sem_op, 1) == -1) {
                perror("semop");
                exit(EXIT_FAILURE);
            }

            printf('Child process %d\n', i);

            // 释放信号量,让父进程执行
            sem_op.sem_num = 0;
            sem_op.sem_op = 1;
            sem_op.sem_flg = 0;
            if (semop(sem_id, &sem_op, 1) == -1) {
                perror("semop");
                exit(EXIT_FAILURE);
            }
        }
    } else {  // 父进程
        for (i = 0; i < 5; i++) {
            // 等待信号量为1,表示轮到自己执行
            sem_op.sem_num = 0;
            sem_op.sem_op = -1;
            sem_op.sem_flg = 0;
            if (semop(sem_id, &sem_op, 1) == -1) {
                perror("semop");
                exit(EXIT_FAILURE);
            }

            printf('Parent process %d\n', i);

            // 释放信号量,让子进程执行
            sem_op.sem_num = 0;
            sem_op.sem_op = 1;
            sem_op.sem_flg = 0;
            if (semop(sem_id, &sem_op, 1) == -1) {
                perror("semop");
                exit(EXIT_FAILURE);
            }
        }
    }

    // 删除信号量集合
    if (semctl(sem_id, 0, IPC_RMID, sem_arg) == -1) {
        perror("semctl");
        exit(EXIT_FAILURE);
    }

    return 0;
}

代码解析

  1. 创建信号量集合:使用 semget 函数创建一个信号量集合,SEM_KEY 为信号量集的键值,1 表示创建单个信号量,IPC_CREAT | 0666 表示创建新的信号量集合并设置权限。

  2. 初始化信号量:使用 semctl 函数将信号量的初始值设置为 1,表示父进程先执行。

  3. 创建子进程:使用 fork 函数创建子进程。

  4. 父子进程循环:父子进程分别进入一个循环,在循环体内使用 semop 函数进行信号量操作。

    • 等待信号量:sem_op.sem_op = -1,表示等待信号量减一,如果信号量值为 0,则阻塞等待。
    • 释放信号量:sem_op.sem_op = 1,表示释放信号量,将信号量值加一。
  5. 删除信号量集合:使用 semctl 函数删除信号量集合。

工作原理

父进程和子进程使用信号量来控制自己的执行顺序。初始时,信号量值为 1,表示父进程先执行。当父进程执行完毕后,它释放信号量,让子进程执行。子进程执行完毕后,再释放信号量,让父进程继续执行。这样就实现了父子进程的交替执行,避免了他们之间的竞争条件,保证了程序的正确性。

总结

本文介绍了使用 Linux 信号量实现父子进程同步的原理和方法,并提供了完整的代码示例。信号量机制是 Linux 系统中常用的进程同步机制,可以有效防止多个进程争抢 CPU 资源,保证程序的正确性和稳定性。

Linux 信号量:父子进程同步实现及 CPU 资源抢夺防止

原文地址: https://www.cveoy.top/t/topic/nsji 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录