当前位置: 首页 > article >正文

linux信号量及其实例

概述

Linux信号量是用于进程间同步和互斥的一种通信机制。本质是计数器
它们通常用于控制对共享资源的访问,以确保只有一个进程可以同时访问该资源。以下是一个详细的教程和C语言代码示例,展示如何使用信号量进行进程间通信。

创建信号量

要使用信号量,我们需要创建一个信号量集。每个信号量集由一个键(key)和一个初始值组成。我们可以使用 semget() 函数创建一个信号量集:

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

#define KEY 1234

int main()
{
    int semid = semget(KEY, 1, IPC_CREAT | 0666);
    if (semid < 0) {
        perror("semget error");
        return 1;
    }
    printf("Semaphore created: %d\n", semid);
    return 0;
}

在上面的代码中,我们使用 KEY 定义一个键值,以便多个进程可以访问同一个信号量集。然后我们使用 semget() 函数创建一个信号量集,该信号量集包含一个信号量,初始值为0。如果创建成功,该函数将返回信号量集的标识符,否则返回-1。

操作信号量

要对信号量进行操作,我们可以使用 semop() 函数。该函数允许我们执行3种操作:增加信号量的值、减少信号量的值、和等待信号量变为0。每个操作由一个结构体来表示,其中包含了信号量的标识符、要执行的操作和操作的参数。例如,以下代码将增加信号量的值:

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

#define KEY 1234

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

int main()
{
    int semid = semget(KEY, 1, IPC_CREAT | 0666);
    if (semid < 0) {
        perror("semget error");
        return 1;
    }

    union semun arg;
    arg.val = 1;
    if (semctl(semid, 0, SETVAL, arg) < 0) {
        perror("semctl error");
        return 1;
    }

    struct sembuf buf;
    buf.sem_num = 0;
    buf.sem_op = 1;
    buf.sem_flg = SEM_UNDO;

    if (semop(semid, &buf, 1) < 0) {
        perror("semop error");
        return 1;
    }

    printf("Semaphore value: %d\n", semctl(semid, 0, GETVAL, arg));
    return 0;
}

在上面的代码中,我们使用 semctl() 函数将信号量的初始值设置为1。然后我们定义一个 sembuf 结构体,该结构体表示要对信号量进行的操作。在这种情况下,我们使用 semop() 函数执行一个操作,该操作将信号量的值增加1。最后,我们使用 semctl() 函数获取信号量的当前值,并将其打印出来。

除了增加信号量的值外,我们还可以使用 semop() 函数减少信号量的值。例如,以下代码将减少信号量的值:

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

#define KEY 1234

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

int main()
{
    int semid = semget(KEY, 1, IPC_CREAT | 0666);
    if (semid < 0) {
        perror("semget error");
        return 1;
    }

    union semun arg;
    arg.val = 1;
    if (semctl(semid, 0, SETVAL, arg) < 0) {
        perror("semctl error");
        return 1;
    }

    struct sembuf buf;
    buf.sem_num = 0;
    buf.sem_op = -1;
    buf.sem_flg = SEM_UNDO;

    if (semop(semid, &buf, 1) < 0) {
        perror("semop error");
        return 1;
    }

    printf("Semaphore value: %d\n", semctl(semid, 0, GETVAL, arg));
    return 0;
}

在上面的代码中,我们使用 semop() 函数将信号量的值减少1。操作由 sembuf 结构体表示,其中 sem_op 的值为-1。最后,我们使用 semctl() 函数获取信号量的当前值,并将其打印出来。

销毁信号量

当不再需要使用信号量时,我们可以使用 semctl() 函数将其销毁。以下是一个示例代码:

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

#define KEY 1234

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

int main()
{
    int semid = semget(KEY, 1, IPC_CREAT | 0666);
    if (semid < 0) {
        perror("semget error");
        return 1;
    }

    if (semctl(semid, 0, IPC_RMID, 0) < 0) {
        perror("semctl error");
        return 1;
    }

    printf("Semaphore destroyed\n");
    return 0;
}

在上面的代码中,我们使用 semctl() 函数将信号量集标识符为 semid 的信号量集销毁。操作由 IPC_RMID 表示。最后,我们打印出一条消息表示信号量已被销毁。

这是一个简单的Linux信号量通信的教程和C语言代码示例。注意,实际应用中可能需要使用更多的信号量以及更复杂的通信模式。


http://www.kler.cn/a/7397.html

相关文章:

  • WebSocket协议在Java中的整合
  • PETR/PETRv2/StreamPETR论文阅读
  • Flowable 构建后端服务(后端以及数据库搭建) Flowable Modeler 设计器搭建(前端)
  • 如何知道表之间的关系(为了知识图谱的构建)
  • Android笔记(三十七):封装一个RecyclerView Item曝光工具——用于埋点上报
  • vue-router的push和replace的区别
  • Vue+H5如何适配各个移动端?
  • netty 实现websocket 携带参数建立连接
  • VSCode卸载、重装配置、常用快捷键
  • 【ChatGPT 】国内无需注册 openai 即可访问 ChatGPT:ChatGPT Sidebar 浏览器扩展程序的安装与使用
  • 【软件设计师10】软件工程
  • SpringSecurity实战解析
  • 为什么系统的Swap变高了?
  • 吴恩达机器学习--逻辑回归
  • 分布式id生成方案及springboot进行集成
  • JavaSE基础(26) 接口
  • 面向对象编程(基础)5:类的成员之二:方法(method)
  • 前后端交互系列之跨域问题
  • centos7离线安装docker
  • 算法刷题打卡042 | 动态规划10
  • vue3之shallowRef以及使用对element-plus table的优化尝试
  • Scrapy-应对反爬虫机制
  • 【vscode】检查到已经改正的错误,没有错误却检查到有错误
  • js跨域与解决
  • [GXYCTF2019]BabyUpload
  • 摸鱼也可以效率翻倍:Python 统计 gitlab 代码量,定量统计发给领导