Linux信号量详解

发布时间:2023-05-22

一、信号量介绍

信号量是一种进程间通信机制,用于同步进程以及保护共享资源。它有三种类型:

  • 二进制信号量:只有两个值,0和1,用于互斥访问共享资源。
  • 计数信号量:其值可以大于1,用于同步。
  • 共享内存信号量:用于控制共享内存的访问。 Linux提供了信号量来实现进程间同步与互斥,提高了系统的并发性和可靠性。

二、信号量相关函数

在Linux中,信号量相关的函数包括:

  • semget: 获取一个信号量集合的标识符。
  • semop: 对信号量集合进行操作。
  • semctl: 对信号量集合进行控制。
int semget(key_t key, int nsems, int semflg);
int semop(int semid, struct sembuf *sops, unsigned nsops);
int semctl(int semid, int semnum, int cmd, ...);

semget函数用于创建或获取一个信号量集合的标识符,semop函数用于对信号量集合进行操作,semctl函数用于对信号量集合进行控制。

三、信号量示例代码

1. 创建信号量集合

#include <stdio.h>
#include <stdlib.h>
#include <sys/sem.h>
int main(int argc, char **argv)
{
    key_t key = ftok(".", 'a');
    int semid = semget(key, 1, IPC_CREAT | 0666);
    if (semid == -1)
    {
        printf("semget error\n");
        exit(1);
    }
    printf("semid=%d\n", semid);
    return 0;
}

该示例代码实现了创建一个新的信号量集合标识符。

2. 初始化信号量集合

#include <stdio.h>
#include <stdlib.h>
#include <sys/sem.h>
int init_sem(int semid, int val)
{
    union semun {
        int val;
        struct semid_ds *buf;
        unsigned short *array;
    } arg;
    arg.val = val;
    return semctl(semid, 0, SETVAL, arg);
}
int main(int argc, char **argv)
{
    key_t key = ftok(".", 'a');
    int semid = semget(key, 1, IPC_CREAT | 0666);
    if (semid == -1)
    {
        printf("semget error\n");
        exit(1);
    }
    if (init_sem(semid, 1) == -1)
    {
        printf("init_sem error\n");
        exit(1);
    }
    printf("semid=%d\n", semid);
    return 0;
}

该示例代码实现了初始化一个新创建的信号量集合,将其值设置为1。

3. 获取和释放信号量

#include <stdio.h>
#include <stdlib.h>
#include <sys/sem.h>
int init_sem(int semid, int val)
{
    union semun {
        int val;
        struct semid_ds *buf;
        unsigned short *array;
    } arg;
    arg.val = val;
    return semctl(semid, 0, SETVAL, arg);
}
int sem_p(int semid)
{
    struct sembuf sops = {0, -1, SEM_UNDO};
    return semop(semid, &sops, 1);
}
int sem_v(int semid)
{
    struct sembuf sops = {0, 1, SEM_UNDO};
    return semop(semid, &sops, 1);
}
int main(int argc, char **argv)
{
    key_t key = ftok(".", 'a');
    int semid = semget(key, 1, IPC_CREAT | 0666);
    if (semid == -1)
    {
        printf("semget error\n");
        exit(1);
    }
    if (init_sem(semid, 1) == -1)
    {
        printf("init_sem error\n");
        exit(1);
    }
    printf("semid=%d\n", semid);
    sem_p(semid);
    printf("Enter the critical area.\n");
    sem_v(semid);
    printf("Exit the critical area.\n");
    return 0;
}

该示例代码实现了获取和释放信号量的操作,用于同步进程对共享资源的访问。

四、总结

本文对Linux信号量进行了详细介绍,包括信号量的类型、相关函数和示例代码。信号量是一种很重要的进程间通信机制,通过它可以保护共享资源、同步进程,提高系统的并发性和可靠性。