vxworks任务通信之信号量

vxworks中信号量分为三种:二进制信号量,互斥信号量,计数信号量

 1.二进制信号量的同步
/*信号量:二进制信号量实现同步
 * 生产者和消费者问题
 * */
#include<stdio.h>
#include<semLib.h>
#include<taskLib.h>
#include<wdLib.h>
#include<unistd.h>
#define TASK_PRIORITY_A 130
#define TASK_PRIORITY_B 130
#define STACK_SIZE 225
int taskId_A, taskId_B;
/*定义信号量*/
SEM_ID semId1, semId2;
/*定义两个Task*/
void taskA(void);
void taskB(void);
int count=20;

int taskDemo() {

	/*创建任务:taskSpawn创建并激活任务*/
	taskId_A=taskSpawn("taskA", TASK_PRIORITY_A, VX_FP_TASK, STACK_SIZE,
			(FUNCPTR)taskA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
	taskId_B=taskSpawn("taskB", TASK_PRIORITY_B, VX_FP_TASK, STACK_SIZE,
			(FUNCPTR)taskB, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
	if (taskId_A==ERROR)
		printf("taskA taskSpawn() failed!\n");
	if (taskId_B==ERROR)
		printf("taskB taskSpawn() failed!\n");
	/*创建二进制信号量,
	 * SEM_Q_PRIORITY
	 * 表示因这个信号量而阻塞的任务在信号量被释放后会根据优先级运行,
	 * SEM_Q_FIFO
	 * 表示信号量释放后先进先出运行
	 * 二进制的初始值
	 * SEM_FULL SEM_EMPTY
	 * 当semTake()时,若该信号量为SEM_EMPTY,则会阻塞
	 * */
	semId1=semBCreate(SEM_Q_PRIORITY,SEM_FULL);
	semId2=semBCreate(SEM_Q_PRIORITY,SEM_EMPTY);
	if (semId1==NULL||semId2==NULL)
		printf("semBCreate() error!\n");

}

/*taskA为生产者*/
void taskA() {

	while (count>0) {
		/*等待消费者通知,semTake()获取信号量semId1*/
		semTake(semId1, WAIT_FOREVER);

		sleep(1);
		printf("Producer create food!\n");

		/*通知消费者,semGive()释放信号量semId2*/
		semGive(semId2);
		count--;

	}

}
/*taskB为消费者*/
void taskB() {

	while (count>0) {
		/*等待生产者通知,semTake()获取信号量semId2*/
		semTake(semId2, WAIT_FOREVER);
		
		sleep(1);
		printf("Consumer eat food!\n");
		
		/*通知生产者,semGive()释放信号量semId1*/
		semGive(semId1);
		count--;

	}
}

Consumer eat food!
Producer create food!
Consumer eat food!
Producer create food!
Consumer eat food!
Producer create food!
Consumer eat food!

 

2.二进制信号量的互斥

 

/*信号量:二进制信号量实现互斥
 * TaskA和TaskB使用打印机
 * */
#include<stdio.h>
#include<semLib.h>
#include<taskLib.h>
#include<wdLib.h>
#include<unistd.h>
#define TASK_PRIORITY_A 130
#define TASK_PRIORITY_B 130
#define STACK_SIZE 225
int taskId_A, taskId_B;
/*定义信号量*/
SEM_ID semId;
/*定义两个Task*/
void taskA(void);
void taskB(void);
int count=20;

int taskDemo() {

	/*创建任务:taskSpawn创建并激活任务*/
	taskId_A=taskSpawn("taskA", TASK_PRIORITY_A, VX_FP_TASK, STACK_SIZE,
			(FUNCPTR)taskA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
	taskId_B=taskSpawn("taskB", TASK_PRIORITY_B, VX_FP_TASK, STACK_SIZE,
			(FUNCPTR)taskB, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
	if (taskId_A==ERROR)
		printf("taskA taskSpawn() failed!\n");
	if (taskId_B==ERROR)
		printf("taskB taskSpawn() failed!\n");
	/*创建二进制信号量,
	 * SEM_Q_PRIORITY
	 * 表示因这个信号量而阻塞的任务在信号量被释放后会根据优先级运行,
	 * SEM_Q_FIFO
	 * 表示信号量释放后先进先出运行
	 * 二进制的初始值
	 * SEM_FULL SEM_EMPTY
	 * 当semTake()时,若该信号量为SEM_EMPTY,则会阻塞
	 * */
	semId=semBCreate(SEM_Q_PRIORITY,SEM_FULL);
	
	if (semId==NULL)
		printf("semBCreate() error!\n");

}


void taskA() {

	while (count>0) {
		/**/
		semTake(semId, WAIT_FOREVER);

		printf("TaskA use the Printer!\n");
		sleep(1);
		printf("TaskA free the Printer!\n");

		/**/
		semGive(semId);
		count--;

	}

}

void taskB() {

	while (count>0) {
		/**/
				semTake(semId, WAIT_FOREVER);

				printf("TaskB use the Printer!\n");
				sleep(1);
				printf("TaskB free the Printer!\n");

				/**/
				semGive(semId);
		count--;

	}
}


 运行结果:

TaskA use the Printer!
TaskA free the Printer!
TaskB use the Printer!
TaskB free the Printer!
TaskA use the Printer!
TaskA free the Printer!
TaskB use the Printer!
TaskB free the Printer!
TaskA use the Printer!

 

3.互斥信号量

互斥信号量是一种特殊类型的二进制信号量,互斥信号量的获取和释放必须在同一个任务中完成,因此专门用于解决互斥问题。互斥信号量在解决互斥时和二进制信号量类似,但是还可以对优先级翻转进行保护,和任务删除保护(任务在持有信号量期间,不会被删除)。

优先级翻转的问题

例如:有优先级为A、B和C三个任务,优先级A>B>C,任务A,B处于挂起状态,等待某一事件发生,任务C正在运行,此时任务C开始使用某一共享资源S。在使用中,任务A等待事件到来,任务A转为就绪态,因为它比任务C优先级高,所以立即执行。当任务A要使用共享资源S时,由于其正在被任务C使用,因此任务A被挂起,任务C开始运行。如果此时任务B等待事件到来,则任务B转为就绪态。由于任务B优先级比任务C高,因此任务B开始运行,直到其运行完毕,任务C才开始运行。直到任务C释放共享资源S后,任务A才得以执行。在这种情况下,优先级发生了翻转,任务B先于任务A运行。 运行过程B->C->A

解决方法:在A要使用共享资源S时,C正在使用,比较A与C的优先级,由于C的优先级小于A,则将C的优先级提升到与A相同,此时B转为就绪态并不会运行,待C释放临界资源后,再将C的优先级调回,运行过程为C->A->B

 

4计数信号量

 计数信号量中,由一个计数器 用来计数。在创建(semCCreate())时可以设置此计数器的初始值。semTake()时,若信号量大于0,则获得该信号量,并减一,若为0,则将任务阻塞并添加至阻塞队列。semGive()时,若阻塞队列中有任务,则唤醒一个,否则信号量计数加1。

 

信号量分三种,其中的大体操作相同:

semGive() 释放信号量

semTake()  获取信号量

semFlush() 解除信号量的阻塞队列中的任务

semDelete() 删除信号量

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值