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

信号量通信机制

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

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‘))==-1)
    {
        perror("ftok");
        exit(EXIT_FAILURE);
    }
    if((sem = semget(key, 3, IPC_CREAT|0770)) == -1)
    {
        perror("semget");
        exit(EXIT_FAILURE);
    }
    printf("sem1 id is: %d\n", sem);
    semctl(sem, 0, IPC_RMID, (struct msquid_ds*)0);  //删除信号量集合
    return 0;
}

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|0666);
    if(semid != -1)
    {
        //初始化
        for(i = 0; i < MAX_SEMAPHORES; i++)
            sem_array[i] = (unsigned short)(i + 1);
        arg.array = sem_array;
        //设置所有信号量的值
        ret = semctl(semid, 0, SETALL, arg);
        if(ret == -1)
            printf("SETALL failed (%d)\n", errno);

        arg.array = sem_read_array;
        //获取所有信号量的值
        ret = semctl(semid, 0, GETALL, arg); //获取所有信号量的值
        if(ret == -1)
            printf("GETALL failed (%d)\n", errno);

        for(i = 0; i < MAX_SEMAPHORES; i++)
            printf("Semaphore %d, value %d\n", i, sem_read_array[i]);

        //逐次获取信号量值
        for(i = 0; i < MAX_SEMAPHORES; i++)
        {
            ret = semctl(semid, i, GETVAL);
            printf("Semaphore %d, value %d\n", i, sem_read_array[i]);
        }
        //删除信号量集合
        ret = semctl(semid, 0, IPC_RMID);
    }
    else
    {
        printf("Could not allocate semaphore (%d)\n", errno);
    }
    return 0;
}

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[4];
sops[0].sem_num = 1;
sops[0].sem_op = -1;
sops[0].sem_flg = 0;

sops[1].sem_num = 2;
sops[1].sem_op = 1;
sops[1].sem_flg = 0;

semop(mysemid, sops, 2)

信号量解决生产者消费者问题,设有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[2];
    union semun
    {
        int val;
        struct semid_ds *buf;
        unsigned short *array;
    }arg;
    key = ftok(".",‘s‘);
    sem_id = semget(key, 2, IPC_CREAT|0644);
    sem_array[0] = 0;   //0号下标 生产者
    sem_array[1] = 100;
    arg.array = sem_array;
    ret = semctl(sem_id, 0, SETALL, arg);  //初始化
    if(ret == -1)
        printf("SETALL failed (%d)\n", errno);
    printf("productor init is %d\n", semctl(sem_id, 0, GETVAL));
    printf("space init is %d\n\n", semctl(sem_id, 1, GETVAL));
}
void del()
{
    semctl(sem_id, 0, IPC_RMID);
}
int main(int argc, char *argv[])
{
    struct sembuf sops[2];

    sops[0].sem_num = 0;
    sops[0].sem_op = 1;          //生产者数量加一
    sops[0].sem_flg = 0;

    sops[1].sem_num = 1;
    sops[1].sem_op = -1;         //消费者数量减一
    sops[1].sem_flg = 0;

    init();
    printf("this is productor\n");
    while(1)
    {
        printf("\n\nbefore produce:\n");
        printf("productor number is %d\n", semctl(sem_id, 0, GETVAL));
        printf("space init is %d\n\n", semctl(sem_id, 1, GETVAL));
        semop(sem_id, (struct sembuf *)&sops[1], 1);  //先预定一个空位
        printf("now producing.....\n");
        semop(sem_id,(struct sembuf *)&sops[0], 1); //生产出一个产品 释放一个产品
        printf("\nafter produce:\n");
        printf("productor number is %d\n", semctl(sem_id, 0, GETVAL));
        printf("space number is %d\n", semctl(sem_id, 1, GETVAL));
        sleep(4);
    }
    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, 2, IPC_CREAT|0644);
}
int main(int argc, char *argv[])
{
    init();
    struct sembuf sops[2];

    sops[0].sem_num = 0;
    sops[0].sem_op = -1;          //产品数量减一
    sops[0].sem_flg = 0;

    sops[1].sem_num = 1;
    sops[1].sem_op = 1;         //空位数量加一
    sops[1].sem_flg = 0;
    printf("this is customer\n");

    while(1)
    {
        printf("\n\nbefore consume:\n");
        printf("productor is %d\n", semctl(sem_id, 0, GETVAL));
        printf("space is %d\n", semctl(sem_id, 1, GETVAL));
        semop(sem_id, (struct sembuf *)&sops[0], 1); //预定一个要消费的产品
        printf("now consuming.....\n");
        semop(sem_id,(struct sembuf *)&sops[1], 1); //增加一个空位
        printf("\nafter consume:\n");
        printf("productor is %d\n", semctl(sem_id, 0, GETVAL));
        printf("space is %d\n", semctl(sem_id, 1, GETVAL));
        sleep(3);
    }
}
时间: 2024-12-29 07:07:24

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

javascript高级程序设计 第十一章--DOM扩展

javascript高级程序设计 第十一章--DOM扩展DOM最主要的扩展就是选择符API.HTML5和Element Traversal Selectors API:定义了两个方法 querySelector() 和 querySelectorAll(),能够基于CSS选择符从DOM中取得元素.querySelector()方法接收一个CSS选择符,返回该模式匹配的第一个元素,querySelectorAll()接收的参数一样,但是返回NodeList实例: matchesSelector()

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

对DOM的两个主要的扩展 Selectors API HTML5 Element Traversal 元素遍历规范 querySelector var body = document.querySelector("body"); var myDiv = document.querySelector("#myDiv"); 取得id为myDiv的元素 var selected = document.querySelector(".selected")

Linux程序设计学习笔记----System V进程间通信(信号量)

关于System V Unix System V,是Unix操作系统众多版本中的一支.它最初由AT&T开发,在1983年第一次发布,因此也被称为AT&T System V.一共发行了4个System V的主要版本:版本1.2.3和4.System V Release 4,或者称为SVR4,是最成功的版本,成为一些UNIX共同特性的源头,例如"SysV 初始化脚本"(/etc/init.d),用来控制系统启动和关闭,System V Interface Definitio

javascript高级程序设计 第十三章--事件

javascript高级程序设计 第十三章--事件js与HTML的交互就是通过事件实现的,事件就是文档或浏览器窗口中发生的一些特定的交互瞬间. 事件流:事件流描述的是从页面中接收事件的顺序,IE的是事件冒泡流,Netscape的是事件捕获流,这个两个是完全相反的事件流概念. 事件冒泡:由最具体的元素接收,然后逐级向上传播到更高级的节点,即事件沿DOM树向上传播,直到document对象. 事件捕获:不大具体的节点应该更早接收到事件,相当于沿DOM节点树向下级传播直到事件的实际目标,在浏览器中,是

Javascript高级程序设计——第三章:基本概念

javascript高级程序设计——第三章:基本概念 一.语法 EMCA-262通过叫做ECMAScript的“伪语言”为我们描述了javascript实现的基本概念 javascript借鉴了C的语法,区分大小写,标示符以字母.下划线.或美元符号($)开头,注释可以用 // 或者/* */ 严格模式: ECMAScript 5引入了严格模式,在严格模式下不确定的行为将得到处理,通过在顶部添加 “use strict”来启用严格模式: function fuc(){ "use strict&qu

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

System V, 曾经也被称为 AT&T System V,是Unix操作系统众多版本中的一支. 传统上,System V 被看作是两种UNIX"风味"之一(另一个是 BSD).然而,随着一些并不基于这两者代码的UNIX实现的出现,例如 Linux 和 QNX, 这一归纳不再准确. System V IPC基础 System V 的IPC机制主要有消息队列.信号量和共享内存3种机制. shell中的 ipcs 命令可以查看当前系统中正在使用的IPC工具. shell中的 ip

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

1. 概述 三种类型的System V IPC:System V 消息队列.System V 信号量.System V 共享内存区 System V IPC在访问它们的函数和内核为它们维护的信息上共享许多类似点.本章讲述所有这些共同属性. 下图汇总了所有System V IPC 函数 2. key_t键.ftok函数 头文件sys/types.h把数据类型key_t定义为一个整数,通常是一个至少32位的整数 #include <sys/ipc.h> key_t ftok (const char

细说linux IPC(五):system V共享内存

system V共享内存和posix共享内存类似,system V共享内存是调用shmget函数和shamat函数.           shmget函数创建共享内存区,或者访问一个存在的内存区,类似系统调用共享内存的open和posix共享内存shm_open函数.shmget函数原型为: #include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); key: 函

细说linux IPC(十):system V 消息队列

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途] system V消息队列和posix消息队列类似,linux系统这两种消息队列都支持.先来看一下system V消息队列相关操作及其函数. msgget()函数创建一个消息队列或打开一个消息队列. #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h&

《JavaScript高级程序设计第五章--引用类型》之Object对象和array对象

这一章主要就是介绍各种内置对象的用法,认识其经常用到的属性和方法. 5.1Object类型 创建objec的方式,一种是new Object(),一种是对象字面量(简化创建包含大量属性的对象的过程) var person = { name = "Nicholas"; age = 27 };//最后一个属性不必添加逗号,ie7等会导致错误 //在使用对象字面量语法时,属性名也可以使用字符串.这里的数值属性会自动转字符串. var person = { "name" :