进程间通信(三)

信号量概述

信号量与已经介绍过的IPC结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。

原型

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

//创建或获取一个信号量组:若成功返回信号量集ID,失败返回-1
int semget(key_t key, int nsems, int semflg);
//对信号量组进程操作,改变信号量的值:成功返回0,失败返回-1
int semop(int semid, struct sembuf *sops, unsigned nsops);
//控制信号量的相关信息
int semctl(int semid, int semnum, int cmd, ...);

int semget(key_t key, int nsems, int semflg);

key就是利用ftok调用的key。
nsems定义的信号量集合中需要几个信号量
semflg 表示获取、创建信号量 宏可以通过man查看

int semop(int semid, struct sembuf *sops, unsigned nsops);

semid 信号量集的ID
struct sembuf *sops
nsops 数组的个数

int semctl(int semid, int semnum, int cmd, …);

semid 信号量集的ID
semnum 需要操作第几个信号量
cmd 通过man semctl查看。

编程实现

编程实现,初始化时临界资源中没有一把锁,我们想要子进程先v操作之后再让父进程pv,代码实现:

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

union semun {
               int              val;    /* Value for SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
};

void pGetKey(int id){
        struct sembuf set;

        set.sem_num = 0;        /* 对0号信号量进行处理 */
        set.sem_op = -1;         /* 每次拿锁之后锁-1 */
        set.sem_flg = 0;

        semop(id,&set,1);
        printf("get the key!\n");
}

void vPutBackKey(int id){
        struct sembuf set;

        set.sem_num = 0;        /* 对0号信号量进行处理 */
        set.sem_op = 1;         /* 每次把锁放回去之后锁+1 */
        set.sem_flg = 0;

        semop(id,&set,1);
        printf("put back the key!\n");
}

int main(){
        int semId;
        int pid;
        key_t key;
        key = ftok(".",1);

        semId = semget(key,1,IPC_CREAT|0666);   //获取或创建信号量

        union semun seminit;
        seminit.val = 0;        //初始钥匙的数量

        semctl(semId,0,SETVAL,seminit); //初始化信号量

        pid = fork();
        if(pid > 0){
                //拿锁
                pGetKey(semId);
                printf("this is father!\n");
                //把锁放回去
                vPutBackKey(semId);
        }else if(pid == 0){
                printf("this is child!\n");
                vPutBackKey(semId);
        }else{
                printf("fork error!\n");
        }


        return 0;
}

相关推荐

  1. 进程通信

    2024-05-12 18:12:06       31 阅读
  2. Python进程通信

    2024-05-12 18:12:06       67 阅读
  3. 20240204进程通信

    2024-05-12 18:12:06       54 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-12 18:12:06       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-12 18:12:06       100 阅读
  3. 在Django里面运行非项目文件

    2024-05-12 18:12:06       82 阅读
  4. Python语言-面向对象

    2024-05-12 18:12:06       91 阅读

热门阅读

  1. 计算方法实验7:实现三次样条插值算法

    2024-05-12 18:12:06       26 阅读
  2. C++ 利用标准库多字节转宽字节字符

    2024-05-12 18:12:06       28 阅读
  3. LeetCode //C - 87. Scramble String

    2024-05-12 18:12:06       31 阅读
  4. 马尔可夫链 学习笔记

    2024-05-12 18:12:06       31 阅读
  5. timestamp和datetime的区别

    2024-05-12 18:12:06       31 阅读
  6. 若依前端分离版-APP(UNI APP)表单添加验证

    2024-05-12 18:12:06       28 阅读
  7. GDB 使用python

    2024-05-12 18:12:06       36 阅读