信号量通信机制

可以看到,跟消息队列类似,也是包括两个结构。

int semget (key_t __key, int __nsems, int __semflg) : 创建信号量集合

  第一个参数:ftok产生的key值

  第二个参数:创建的信号量个数

  第三个参数:权限信息

创建信号量例子:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<sys/types.h> int main(int argc, char * argv[])
{
int sem;
key_t key;
if((key = ftok(".",'B'))==-)
{
perror("ftok");
exit(EXIT_FAILURE);
}
if((sem = semget(key, , IPC_CREAT|)) == -)
{
perror("semget");
exit(EXIT_FAILURE);
}
printf("sem1 id is: %d\n", sem);
semctl(sem, , IPC_RMID, (struct msquid_ds*)); //删除信号量集合
return ;
}

int semctl (int __semid, int __semnum, int __cmd, ...) :控制信号量集合、信号量

  第一个参数:要操作的信号量集合标识

  第二个参数:信号量编号。如果操作整个信号量集合无意义;如果是某个信号量,为信号量下标。

  第三个参数:执行的操作。 如果对整个集合操作,则包括:IPC_RMID, IPC_SET, IPC_STAT, IPC_INFO

              如果是对某个或某些信号量操作,则包括GETPID、GETVAL、GETALL、GETNCNT、GETZCNT、SETVAL、SETALL.具体见图

设置读取信号量的例子

#include<stdio.h>
#include<sys/types.h>
#include<sys/sem.h>
#include<errno.h>
#define MAX_SEMAPHORES 5
int main(int argc, char *argv[])
{
int i, ret, semid;
unsigned short sem_array[MAX_SEMAPHORES];
unsigned short sem_read_array[MAX_SEMAPHORES];
union senmun
{
int val;
struct semid_ds *buf;
unsigned short *array;
}arg;
//创建信号量集合
semid = semget(IPC_PRIVATE, MAX_SEMAPHORES, IPC_CREAT|);
if(semid != -)
{
//初始化
for(i = ; i < MAX_SEMAPHORES; i++)
sem_array[i] = (unsigned short)(i + );
arg.array = sem_array;
//设置所有信号量的值
ret = semctl(semid, , SETALL, arg);
if(ret == -)
printf("SETALL failed (%d)\n", errno); arg.array = sem_read_array;
//获取所有信号量的值
ret = semctl(semid, , GETALL, arg); //获取所有信号量的值
if(ret == -)
printf("GETALL failed (%d)\n", errno); for(i = ; i < MAX_SEMAPHORES; i++)
printf("Semaphore %d, value %d\n", i, sem_read_array[i]); //逐次获取信号量值
for(i = ; i < MAX_SEMAPHORES; i++)
{
ret = semctl(semid, i, GETVAL);
printf("Semaphore %d, value %d\n", i, sem_read_array[i]);
}
//删除信号量集合
ret = semctl(semid, , IPC_RMID);
}
else
{
printf("Could not allocate semaphore (%d)\n", errno);
}
return ;
}

int semop (int __semid, struct sembuf *__sops, size_t __nsops) :操作信号量

第一个参数:要操作的信号量集合ID

第二个参数

struct sembug{
unsigned short sem_num;
short sem_op;
short sem_flg;
};
  • sem_num:操作的信号量编号
  • sem_op:用于信号量的操作,正数表示增加信号量的值;负数表示减小信号量的值;0表示测试当前值是否为0
  • sem_flg:操作标识,IPC_NOWAIT,如果等待立即返回;SEM_UNDO,当进程退出后,该进程对sem进行的操作将被撤销。

下面的代码,对信号量1做P操作(get),对信号量2做V操作(release)

struct sembuf sops[];
sops[].sem_num = ;
sops[].sem_op = -;
sops[].sem_flg = ; sops[].sem_num = ;
sops[].sem_op = ;
sops[].sem_flg = ; semop(mysemid, sops, )

信号量解决生产者消费者问题,设有100个空位的缓冲池。

下面代码,经验证可用。

生产者代码:

#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<errno.h>
int sem_id;
void init()
{
key_t key;
int ret;
unsigned short sem_array[];
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
}arg;
key = ftok(".",'s');
sem_id = semget(key, , IPC_CREAT|);
sem_array[] = ; //0号下标 生产者
sem_array[] = ;
arg.array = sem_array;
ret = semctl(sem_id, , SETALL, arg); //初始化
if(ret == -)
printf("SETALL failed (%d)\n", errno);
printf("productor init is %d\n", semctl(sem_id, , GETVAL));
printf("space init is %d\n\n", semctl(sem_id, , GETVAL));
}
void del()
{
semctl(sem_id, , IPC_RMID);
}
int main(int argc, char *argv[])
{
struct sembuf sops[]; sops[].sem_num = ;
sops[].sem_op = ; //生产者数量加一
sops[].sem_flg = ; sops[].sem_num = ;
sops[].sem_op = -; //消费者数量减一
sops[].sem_flg = ; init();
printf("this is productor\n");
while()
{
printf("\n\nbefore produce:\n");
printf("productor number is %d\n", semctl(sem_id, , GETVAL));
printf("space init is %d\n\n", semctl(sem_id, , GETVAL));
semop(sem_id, (struct sembuf *)&sops[], ); //先预定一个空位
printf("now producing.....\n");
semop(sem_id,(struct sembuf *)&sops[], ); //生产出一个产品 释放一个产品
printf("\nafter produce:\n");
printf("productor number is %d\n", semctl(sem_id, , GETVAL));
printf("space number is %d\n", semctl(sem_id, , GETVAL));
sleep();
}
del();
}

消费者代码:

#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<errno.h>
int sem_id;
void init()
{
key_t key;
key = ftok(".", 's');
sem_id = semget(key, , IPC_CREAT|);
}
int main(int argc, char *argv[])
{
init();
struct sembuf sops[]; sops[].sem_num = ;
sops[].sem_op = -; //产品数量减一
sops[].sem_flg = ; sops[].sem_num = ;
sops[].sem_op = ; //空位数量加一
sops[].sem_flg = ;
printf("this is customer\n"); while()
{
printf("\n\nbefore consume:\n");
printf("productor is %d\n", semctl(sem_id, , GETVAL));
printf("space is %d\n", semctl(sem_id, , GETVAL));
semop(sem_id, (struct sembuf *)&sops[], ); //预定一个要消费的产品
printf("now consuming.....\n");
semop(sem_id,(struct sembuf *)&sops[], ); //增加一个空位
printf("\nafter consume:\n");
printf("productor is %d\n", semctl(sem_id, , GETVAL));
printf("space is %d\n", semctl(sem_id, , GETVAL));
sleep();
}
}

【linux高级程序设计】(第十一章)System V进程间通信 3的更多相关文章

  1. 第三十一章 System V信号量(二)

    用信号量实现进程互斥示例 #include <unistd.h> #include <sys/types.h> #include <stdlib.h> #inclu ...

  2. 读书笔记 - js高级程序设计 - 第十一章 DOM扩展

      对DOM的两个主要的扩展 Selectors API HTML5  Element Traversal 元素遍历规范 querySelector var body = document.query ...

  3. 《JavaScript高级程序设计》——第二章在HTML使用JavaScript

    这章讲的是JavaScript在HTML中的使用,也就是<script>元素的属性.书中详细讲了async.defer.src和type四个<script>的属性. 下面是对第 ...

  4. ipc - System V 进程间通信机制

    SYNOPSIS 总览 # include <sys/types.h> # include <sys/ipc.h> # include <sys/msg.h> # ...

  5. 【linux高级程序设计】(第十一章)System V进程间通信 1

    System V, 曾经也被称为 AT&T System V,是Unix操作系统众多版本中的一支. 传统上,System V 被看作是两种UNIX"风味"之一(另一个是 B ...

  6. Linux进程通信 之 信号灯(semphore)(System V && POSIX)

    一. 信号灯简介 信号灯与其他进程间通信方式不大相同,它主要提供对进程间共享资源访问控制机制. 相当于内存中的标志,进程可以根据它判定是否能够访问某些共享资源,同时,进程 也可以修改该标志.除了用于访 ...

  7. 《Unix网络编程》卷2 读书笔记 第3章- System V IPC

    1. 概述 三种类型的System V IPC:System V 消息队列.System V 信号量.System V 共享内存区 System V IPC在访问它们的函数和内核为它们维护的信息上共享 ...

  8. 第11章 System V 信号量

    11.1 概述 信号量按功能分:二值信号量.计数信号量.信号量集:其中二值信号量和计数信号量指的是Posix信号量,信号量集指的是System V信号量.

  9. 第6章 System V消息队列

    6.1 概述 System V消息队列在内核中是list存放的,头结点中有2个指针msg_first 和msg_last.其中每个节点包含:下个节点地址的指针.类型.长度.数据等. 6.2 函数 6. ...

  10. 第3章 System V IPC

    3.1 概述 System V IPC 包含:System V消息队列.System V信号量.System V共享内存. 3.2 key_t 键和 ftok函数 这三种类型的System V IPC ...

随机推荐

  1. PHP.15-mysqli

    从PHP5.0开始可以使用mysql(i), 是一个面向对象的技术(新加功能都会以对象形式添加) i:表示改进,1. 功能增加了, 2,效率大大增加(以后的PHP项目改成mysqli),3,更稳定 m ...

  2. python - web自动化测试 - 元素操作 - 鼠标键盘

    # -*- coding:utf-8 -*- ''' @project: web学习 @author: Jimmy @file: 鼠标操作.py @ide: PyCharm Community Edi ...

  3. JMeter获取复杂的JSON串中的参数的值

    大家好,这篇博文中主要是介绍怎么用JMeter的BeanShell去获取复杂的JSON串中的某个参数的值,这将 便于我们用JMeter做出更完美的自动化测试: 首先有这样一个json串: { &quo ...

  4. Pytest框架介绍

    Pytest框架介绍.安装 pytest是python测试框架,与python自带的unittest测试框架类似,但是比unittest框架使用起来更简洁,功能更强大 pytest特征 1:断言提示信 ...

  5. QA 、 QC & QM软件测试入门专业名词解释 -- 灌水走起

    灌水正式开始: 说明:我的农田,我灌水 一.QA . QC & QM: 1.QM QM 是quanlity management,中文名称是品质管理 2.QA QA是英文quality ass ...

  6. day06_01 上节回顾

    1.0 extend 扩展方法及"+"的对比 "+"不会改变数组的内容,而extend会改变数组的内容 2.0 sort扩展sorted() a = [1,2, ...

  7. 百度webuploader上传 1

    百度webupload网址:http://fex.baidu.com/webuploader/ 引入js和css <script src="../../Content/webuploa ...

  8. js万年历

    首先,注意: 1.延迟执行     window.setTimeout(    ,     )     里面的时间是以毫秒计算的 2.间隔执行    window.setInterval(     , ...

  9. Python函数参数中的冒号与箭头

    在一些Python的工程项目中,我们会看到函数参数中会有冒号,有的函数后面会跟着一个箭头,你可能会疑惑,这些都是什么东西? 其实函数参数中的冒号是参数的类型建议符,告诉程序员希望传入的实参的类型.函数 ...

  10. Struts1 生成Action请求的几种方式分析

    1 直接硬编码 <a href="/Lesson14_Struts1_Demo1//user/regUserDo.do">注册</a><br/> ...