semctl semget semop 函数系列构成的 信号量

a:focus {
outline: thin dotted #333;
outline: 5px auto -webkit-focus-ring-color;
outline-offset: -2px;
}
a:hover {
outline: 0;
}
a:active {
outline: 0;
}
a:hover {
color: #005580;
text-decoration: underline;
}
blockquote small:before {
content: ‘\2014 \00A0‘;
}
q:before {
content: "";
}
q:after {
content: "";
}
blockquote:before {
content: "";
}
blockquote:after {
content: "";
}

semctl semget semop 函数系列构成的 信号量

linux服务器编程

信号量原语

简介

信号量是由 Dijkstra 提出的解决多进程沟通和并发编程问题的特殊变量,这种变量只能取自然数,而且只支持两种操作: wait & signal 。它主要处理多个进程访问资源的问题,通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域,而临界区域是指执行数据更新的代码需要独占式地执行。

实现方式

首先创建一个信号量 SV,并且使用一个整数唯一的标识信号量(这个标识量是跨越进程存在的,即在不同的进程中同一个信号量也能唯一的标识该事件)。只有两种 一种是 wait 操作,一种是 signal 操作,不过为了避免和linux的概念重复,又被称为 P 操作 和 V 操作

  • P(SV) :如果 SV 大于 0,那么 SV 的值 减一,这里的值指的是信号量所带的值,而不是标识信号量的整数,就和结构体名和结构体的内的一个变量一样,减的是变量。如果是SV==0,那么就挂起该进程的执行
  • V(SV):如果有其他进程由 因等待SV 挂起,那么 激活给他,如果没有 那么就 SV 加 一

上面很难理解对吧,举个例子吧。

我有两个进程 A & B,他们分想访问资源 C (访问过程的代码为关键代码),利用 信号量 来保证同时只有唯一的一个。比如

  1. 开始时首先设置 SV 的值 为 1
  2. 假设 A 优先 走到 关键代码区域,它会执行 P(SV) ,根据上面的操作,他会减 1 ,同时执行关键的代码。
  3. 在 A 执行关键代码的时候,B运行到了关键代码出,执行 P(SV

    ),它会则会挂起该进程,直到 A 执行完关键代码,并且 执行了 V(SV)

但必须强调的是 P(SV),V(SV ),都必须是原子操作。是由

sys/sem.h 的定义的函数实现的。

有些分类方式业在这提一下啊

信号量按其用途可分为两种:

􀁺 公用信号量:联系一组并发进程,相关的进程均可在此信号量上执行P 和V操作。初值常常为1,用于实现进程互斥。

􀁺 私有信号量:联系一组并发进程,仅允许此信号量拥有的进程执行P 操作,而其他相关进程可在其上施行V 操作。初值常常为0 或正整数,多用于并发进程同步。

信号量按其取值可分为两种:

􀁺 二元信号量:仅允许取值为0 和1,主要用于解决进程互斥问题。

􀁺 一般信号量:允许取值为非负整数,主要用于解决进程同步问题。

函数集

创建or 获得

int semget(key_t key, int num_sems, int sem_flags);  

第一个参数key是整数值(唯一非零),不相关的进程可以通过它访问一个信号量,它代表程序可能要使用的某个资源,程序对所有信号量的访问都是间接的,程序先通过调用semget函数并提供一个键,再由系统生成一个相应的信号标识符(semget函数的返回值),只有semget函数才直接使用信号量键,所有其他的信号量函数使用由semget函数返回的信号量标识符。如果多个程序使用相同的key值,key将负责协调工作。

第二个参数num_sems指定信号集中信号的个数

具体的值是根据你使用信号量的目的,如果你想要实现进程之间的互斥操作,设置为1 ,而如果想要实现多进程的同步问题,那么至少得大于一。在为零的情况下,是获取该信号量。

第三个参数sem_flags是一组标志,当想要当信号量不存在时创建一个新的信号量,可以和值IPC_CREAT做按位或操作。设置了IPC_CREAT标志后,即使给出的键是一个已有信号量的键,也不会产生错误。而IPC_CREAT | IPC_EXCL则可以创建一个新的,唯一的信号量,如果信号量已存在,返回一个错误。

semget函数成功返回一个相应信号标识符(非零),失败返回-1.

信号量操作

int semop(int sem_id, struct sembuf *sem_opa, size_t num_sem_ops);

它用来实现信号量的 P,V 操作,利用是的结stuct sembuf来指示操作内容

struct sembuf{
    short sem_num;//除非使用一组信号量,否则它为0
    short sem_op;//信号量在一次操作中需要改变的数据,通常是两个数,一个是-1,即P(等待)操作,
                    //一个是+1,即V(发送信号)操作。
    short sem_flg;//通常为SEM_UNDO,使操作系统跟踪信号,
                    //并在进程没有释放该信号量而终止时,操作系统释放信号量
};

结构体中的变量含义为

sem_num : 指定操作信号量集中的第 sem_num+1 个信号量,一般设置为 0,表示操作第一个

sem_flag:

IPC_NOWAIT :设置信号量操作不等待

SEM_UNDO : 选项会让内核记录一个与调用进程相关的UNDO记录,如果该进程崩溃,则根据这个进程的UNDO记录自动恢复相应信号量的计数值

sem_op : 表示 操作信号量的方式,实现 P | V 的操作

sem_op 意义
大于0 将 sem_val + opt ,但要求有写权限
等于 0 在没有设置 IPC_NOWAIT 的情况下,会挂起 等待 sem_val==0的情况发生,发生则立即返。但设置的话,就会立即返回错误信息EAGAIN
小于 0 在没有设置 IPC_NOWAIT的情况下,会等待 sem_op的绝对值小于 等于sem_val的值,小于的话,就减去它,并且放回,设置的话,与 等于0 的情况基本一致

等于 0 一般被称为 等待 0 ,而小于 0 则可以称为 等待可减

信号量设置

int semctl(int sem_id, int sem_num, int command, ...);

该函数用于对信号量直接设置

sem_id 为信号量级标识

sem_um 指定被操作信号量在信号量集中的编号

command 为操作命令

而... 代表可扩展参数,推荐使用一下啊的结构体填充

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) */
};

而该结构体中的 semid_ds 和 seminfo 的结构体,seminfo 表示信号量系统资源配置信息,semid_ds则是一个内核结构体,在 semget 函数创建信号量时,被初始化和关联

的具体信息可以去man 一下 该函数,

时间: 2024-09-29 23:01:09

semctl semget semop 函数系列构成的 信号量的相关文章

进程间的通信---信号量(semget,semctl,semop)

信号量的本质是一种数据操作锁,它本身不具有数据交换的功能,而是通过控制其他的通信资源(文件,外部设备)来实现进程间通信,它本身只是一种外部资源的标识.信号量就是一个计数器. 当请求一个使用信号量来表示的资源时,进程需要先读取信号量的值来判断资源是否可用.大于0,资源可以请求,等于0,无资源可用,进程会进入睡眠状态直至资源可用.当一个进程不再使用一个信号量控制的共享资源时,信号量的值+1,对信号量的值进行的增减操作为原子操作,这是由于信号量主要的作用是维护资源的互斥或多进程的同步访问.而信号量的创

【函数】Oracle函数系列(1)--字符函数

[函数]Oracle函数系列(1)--字符函数 1  BLOG文档结构图 2  前言部分 2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~: ① 常见字符函数(lower.upper.initcap.concat.substr.length.intr.lpad.rpad.trim.chr.ascii.replace.translate)的使用 ② 判断字符串中是否含有汉字 ③ substr和instr的联合使用 ④

深入理解javascript函数系列第三篇

前面的话 函数是javascript中特殊的对象,可以拥有属性和方法,就像普通的对象拥有属性和方法一样.甚至可以用Function()构造函数来创建新的函数对象.本文是深入理解javascript函数系列第三篇--属性和方法 属性 [length属性] 函数系列第二篇中介绍过,arguments对象的length属性表示实参个数,而函数的length属性则表示形参个数 function add(x,y){ console.log(arguments.length)//3 console.log(

cumsum累计函数系列:pd.cumsum()、pd.cumprod()、pd.cummax()、pd.cummin()

cum系列函数是作为DataFrame或Series对象的方法出现的,因此命令格式为D.cumsum() 举例: D=pd.Series(range(0,5)) 1. cumsum 2. cumprod 3. cummax 4. cummin 参考文献: [1]Pandas —— cum累积计算和rolling滚动计算 原文地址:https://www.cnblogs.com/nxf-rabbit75/p/10669582.html

#incldue<cctype>函数系列

#include <cctype>的函数 c++中应该是#include <cctype> c中应该是#include <ctype.h> 以下为字符函数库中常用的函数: 函数名称 返回值 isalnum() 如果参数是字母数字,即字母或数字,该函数返回true isalpha() 如果参数是字母,该函数返回真 isblank() 如果参数是空格或水平制表符,该函数返回true iscntrl() 如果参数是控制字符,该函数返回true isdigit() 如果参数是数

javascript函数系列总结

目录链接 [1]引用类型之函数Funtion() [2]函数表达式 [3]闭包 [4]函数中的私有变量和特权方法 [5]匿名函数模仿块级作用域 [6]函数自执行的错误与正确示范

线程等待WaitXXXXX()函数系列之WaitForSingleObject和WaitForMultipleObject

Wait*()函数族可以来实现事件的检测,改函数可以实现单信号和多信号的侦测. 可能我这么说大家可能会有点迷迷糊糊.不急,我们先来介绍两个函数. 第一个是用于单信号侦测.WaitForSingleObject() 函数原型 DWORD WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds ); hHandle对象句柄.可以指定一系列的对象,如Event.Job.Memory resourcenotification.Mutex.Pro

深入理解javascript函数系列第四篇——ES6函数扩展

× 目录 [1]参数默认值 [2]rest参数 [3]扩展运算符[4]箭头函数 前面的话 ES6标准关于函数扩展部分,主要涉及以下四个方面:参数默认值.rest参数.扩展运算符和箭头函数 参数默认值 一般地,为参数设置默认值需进行如下设置 function log(x, y) { y = y || 'World'; console.log(x, y); } 但这样设置实际上是有问题的,如果y的值本身是假值(包括false.undefined.null.''.0.-0.NaN),则无法取得本身值

CCTYPE函数系列

#include <cctype>的函数 c++中应该是#include <cctype> c中应该是#include <ctype.h> 以下为字符函数库中常用的函数: 函数名称 返回值 isalnum() 如果参数是字母数字,即字母或数字,该函数返回true isalpha() 如果参数是字母,该函数返回真 isblank() 如果参数是空格或水平制表符,该函数返回true iscntrl() 如果参数是控制字符,该函数返回true isdigit() 如果参数是数