博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【进程】进程通信-信号量(信号灯)
阅读量:6157 次
发布时间:2019-06-21

本文共 3437 字,大约阅读时间需要 11 分钟。

信号量

  信号量(又名:信号灯)与其他进程间通信方式不大相同,主要用途是保护临界资源。

  进程可以根据它判断是否能够访问某些共享资源。除了用于访问控制外,还可用于进程同步。

  当进程A要获取临界资源S时,首先要获取临界资源的信号量M,M的初始值为1,当获取到M并发现M的值大于1时,可以反问临界资源M,且信号量-1,M=0。

  当进程B也要访问临界资源S时,也要首先获取临界资源S的信号量M,发现M的值为0时,无法获取临界资源S,进程B阻塞等待。

  当进程A访问完临界资源后,信号量M加1,变为M=1,同时唤醒进程B,使得B能够访问临界资源S,以此类推,交替访问临界资源S。

 

分类

  二值信号灯:信号灯的值只能取0或者1,类似于互斥锁。但两者有不同:信号灯强调共享资源,只要共享资源可用,其他进程同样可以修改信号灯的值互斥锁更强调进程,占用资源的进程使用完资源后,必须由进程本身来解锁。

  计数信号灯:信号灯的值可以取任意非负值。

 

创建/打开

#include
#include
#include
int semget(key_t key,int nsems,int semflg)

 

  1. key:键值,由ftok获得。
  2. nsems:指定打开或者新创建的信号灯中将包含信号灯的数目。
  3. semflg:标识,同消息队列,访问权限。

 

信号量的操作

int semop(int semid,struct sembuf *sops,unsigned nsops)
  • 功能:对信号量进行控制。
  • semid:信号量集的ID
  • sops:是一个操作数组,表明要进行什么操作。
  • nsops:sops所指向的数组元素个数。

 

struct sembuf{    unsigned short sem_num;  /*表示你要获取信号量在信号集中的索引*/    short sem_op;    /*决定获取还是释放信号量*/    short sem_flg;}

  sem_op:决定获取还是释放信号量

  1. 0:等待,直到信号灯的值变成0
  2. 1:释放资源,V操作
  3. -1:分配资源,P操作

  Sem_flg:信号操作标志,可能选择有两种:

  1. IPC_NOWAIT:对信号的操作不能满足时,semop不会阻塞,并立即返回,同时设定错误信息。
  2. IPC_UNDO:程序结束时(无论正常还是非正常结束)释放信号量,这样做的目的在于避免程序在异常情况下结束时未将锁定的资源解锁,造成该资源永远锁定。

 

信号量实例

 

1 /**********************************************************  2  *程序要求:   创建两个进程,通过信号灯控制进程中一段代码的执行循序。  3  *功能描述:   本程序通过使用信号灯,实现了一种基于父子进程的简单的进程同步。  4  **********************************************************/   5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 13 /* 14 * 函数入口 15 * */ 16 int main() 17 { 18 int pid,semid; 19 key_t semkey; 20 21 if((semkey=ftok("./samaphore.c",1))<0)//将文件路径和项目ID(后面那个“1“)转换为System V IPC Key 22 { 23 printf("ftok failed\n"); 24 exit(EXIT_FAILURE); 25 } 26 printf("ftok ok, semkey=%d\n",semkey); 27 if((semid=semget(semkey,1,IPC_CREAT|IPC_EXCL|0700))<0)//创建信号灯集,其中包含1个信号灯 28 { 29 printf("semget failed\n");30 exit(EXIT_FAILURE); 31 } 32 printf("semget ok, semid=%d\n",semid); 33 34 if((semctl(semid,0,SETVAL,1))<0)//设置semid对应的信号集中第一个信号灯的semval为1。 35 { 36 printf("semctl set semval failed\n");37 exit(EXIT_FAILURE); 38 } 39 printf("semctl set semval ok\n"); 40 if((pid=fork())<0) 41 { 42 printf("fork failed\n"); 43 exit(EXIT_FAILURE); 44 } 45 else if(pid>0)//父进程,先索取共享资源,而后释放 46 { 47 struct sembuf p_op_buf,v_op_buf; 48 49 p_op_buf.sem_num=0; 50 p_op_buf.sem_op=-1; //-1为分配资源,0为等待,1为释放资源51 if(semop(semid,&p_op_buf,1)<0)//以上三行向semid代表的信号灯集的第一个信号灯申请一个资源,即使semval减1 52 { 53 printf("semop failed\n"); 54 exit(EXIT_FAILURE); 55 } 56 printf("father get the semaphore\n"); 57 sleep(3); 58 printf("father release the semaphore\n"); 59 v_op_buf.sem_num=0; 60 v_op_buf.sem_op=1; //释放资源61 v_op_buf.sem_flg=0; 62 if(semop(semid,&v_op_buf,1)<0)//以上三行将释放一个资源给semid代表的信号灯集第一个信号灯 63 { 64 printf("semop release semaphore failed\n"); 65 exit(EXIT_FAILURE); 66 } 67 } 68 else//子进程不断申请共享资源,申请到后声明一下,然后释放 69 { 70 struct sembuf p_op_buf,v_op_buf; 71 sleep(1);//等待父进程将唯一的资源占用 72 printf("child wait for the semaphore\n"); 73 p_op_buf.sem_num=0; 74 p_op_buf.sem_op=-1; 75 p_op_buf.sem_flg=0;//该标志位不用要清零,此处不清零将出现错误 76 if(semop(semid,&p_op_buf,1)<0)//向semid代表的信号灯集的第一个信号灯申请一个资源,申请不到就会阻塞,直到有了资源 77 { 78 printf("semop get semaphore failed\n"); 79 exit(EXIT_FAILURE); 80 } 81 printf("child get the semaphore\n"); 82 if(semctl(semid,0,IPC_RMID,0)<0) 83 { 84 printf("semctl remove semaphore set failed\n"); 85 exit(EXIT_FAILURE); 86 } 87 } 88 }
View Code

 

 

转载地址:http://jkafa.baihongyu.com/

你可能感兴趣的文章
[BTS] Could not find stored procedure 'mp_sap_check_tid'
查看>>
PLSQL DBMS_DDL.ALTER_COMPILE
查看>>
Activity生命周期
查看>>
高仿UC浏览器弹出菜单效果
查看>>
Ubuntu忘记密码,进不了系统的解决方法
查看>>
[原创]白盒测试技术思维导图
查看>>
<<Information Store and Management>> 读书笔记 之八
查看>>
Windows 8 开发之设置合约
查看>>
闲说HeartBeat心跳包和TCP协议的KeepAlive机制
查看>>
MoSQL
查看>>
Hibernate多对一外键单向关联(Annotation配置)
查看>>
《CLR via C#》读书笔记 之 方法
查看>>
设计模式:组合模式(Composite Pattern)
查看>>
ContentValues 和HashTable区别
查看>>
LogicalDOC 6.6.2 发布,文档管理系统
查看>>
给PowerShell脚本传递参数
查看>>
实战2——Hadoop的日志分析
查看>>
利用FIFO进行文件拷贝一例
查看>>
Ecshop安装过程中的的问题:cls_image::gd_version()和不支持JPEG
查看>>
resmgr:cpu quantum等待事件
查看>>