一、信号量(Semaphores)
信号量有助于协调多任务应用程序的活动。任务最明显的通信方式是通过各种共享数据结构。由于单个进程中的所有任务都存在于单个线性地址空间中,因此在任务之间共享数据结构很简单。在不同任务上下文中运行的代码可以直接引用全局变量、线性缓冲区、环形缓冲区、链接列表和指针。然而,虽然共享地址空间简化了数据交换,但对内存的互锁访问对于避免数据损坏至关重要。确保独占访问共享资源的方法之一是信号量机制。此外,信号量可用于任务同步。
xenomai 中的信号量提供了快速的任务间通信的方式。信号量是处理互斥和任务同步需求的主要手段。一般来说,我们可以说:
信号量的接口由两个操作组成,V和P,它们影响与信号量相关的内部计数器。V来自荷兰语“Verhogen”,意为“增加”;P来自荷兰语“Proberen”,意思是“努力减少”。
“V”(信号、释放、给出)操作递增计数器并立即返回(释放信号)。
“P”操作(等待、获取、获取)减少计数器并立即返回,除非计数器已经为零,并且操作阻塞,直到另一个进程释放信号量(挂起信号)。
Xenomai中的信号量是计数信号量,它可以用来保护一个资源的多个实例,这与只使用0和1值的二进制信号量形成对比。二进制信号量在Xenomai中称为“互斥量”,并有一个单独的API。
二、信号量机制常用的API
信号量 Alchemy API.
1、创建一个计数信号量:
int rt_sem_create(RT_SEM *sem, const char *name, unsigned long icount, int mode)
其中icount是计数器的初始值,mode可以是S_FIFO或S_PRIO,这使得任务分别按FIFO(先进先出)顺序或优先级顺序挂起在信号量上。
2、挂起一个信号量,使计数器icount减1.
int rt_sem_p(RT_SEM *sem, RTIME timeout)
3、发出信号,使icount计数器加1:
int rt_sem_v(RT_SEM *sem)
4、广播一个信号量,即发出一个信号量,解除所有等待它的任务的阻塞(若任务间是同等级将按启动顺序,若设置了优先级将以优先级顺序执行任务的顺序):
int rt_sem_broadcast(RT_SEM *sem)
5、删除一个信号量:
int rt_sem_delete(RT_SEM *sem)
三、通过两个任务修改一个全局变量
任务要求:
两个任务(taskOne和taskTwo)竞相更改名为“global”的全局变量的值,程序的目标是切换全局变量的值(1和0)。TaskOne递增“global”值,taskTwo递减该值。
1、利用普通循环
程序3a:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#include <alchemy/sem.h>
#define ITER 10
static RT_TASK t1;
static RT_TASK t2;//建立两个实时任务
int global = 0;//定义一个global变量
void taskOne(void *arg)//任务一功能函数,递增global
{
int i;
for (i=0; i < ITER; i++) {
printf("I am taskOne and global = %d................\n", ++global);
}
}
void taskTwo(void *arg)//任务二功能,递减global
{
int i;
for (i=0; i < ITER; i++) {
printf("I am taskTwo and global = %d----------------\n", --global);
}
}
int main(int argc, char* argv[]) {
rt_task_create(&t1, "task1", 0, 1, 0);
rt_task_create(&t2, "task2", 0, 1