信号量通信机制

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

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. 4034: [HAOI2015]树上操作

    4034: [HAOI2015]树上操作 链接 思路: 树链剖分.操作:单点修改,路径查询,子树修改. 代码: #include<cstdio> #include<algorithm ...

  2. DOS程序员手册(一)

    当今MS-Windows横扫大江南北,让我们这就来研究一下它的祖宗——MS-DOS! 这本书很难得,希望读者好好学习! DOS程序员手册(一) DOS教程 (以下内容全部为原作者的阐述,照样保留) 这 ...

  3. WPF and Silverlight.ComboBox 如何通过 Binding IsDropDownOpen 实现下拉菜单展开

    In the WPF example the Popup and the ToggleButton (the arrow on the right) are bound with the proper ...

  4. 【APUE】Chapter11 Threads

    看完了APUE第三版的Chapter11 Threads,跟着书上的demo走了一遍,并且参考了这个blog(http://www.cnblogs.com/chuyuhuashi/p/4447817. ...

  5. python中subprocess.Popen执行命令并持续获取返回值

    先举一个Android查询连接设备的命令来看看Python中subprocess.Popen怎么样的写法.用到的命令为 adb devices. import subprocess order='ad ...

  6. Python全栈工程师(面向对象)

    ParisGabriel                每天坚持手写  一天一篇  决定坚持几年 为了梦想为了信仰    开局一张图 Python人工智能从入门到精通 day16补充: 异常处理 文件 ...

  7. python import模块熟悉方法

    python import导入的可用模块很多,新增速度较快,无法一次性全部掌握. 掌握熟悉一种模块的方法是非常有价值的技能. 探究模块可以从python解释器入手,具体流程记录如下: 以os模块为例: ...

  8. ZOJ 3724 Delivery 树状数组好题

    虽然看起来是求最短路,但因为条件的限制,可以转化为区间求最小值. 对于一条small path [a, b],假设它的长度是len,它对区间[a, b]的影响就是:len-( sum[b]-sum[a ...

  9. SpringMVC<一> 基本结构与配置

    刚刚踏入SpringMVC的学习,有一定Strust2的使用经验,边看书看博客,边总结,如有不对的地方还希望各位大佬多多指正. Spring 响应过程与结构 (1)用户在客户端发送一个HTTP请求,W ...

  10. android瀑布流照片墙实现代码详解

    照片墙的实现,是需要往手机里面添加很多图片的,如果没有对资源进行合理的释放,程序很快就会出现OOM.所以需要用到LruCache算法来缓存图片. 1,首先是图片资源类,这个类中包含了很多图片链接. p ...