SmlOS四-FIFO缓冲区实现
先进先出队列
FIFO(First in First out)
结构体
struct FIFO32
{
int *buf; //缓冲区指针
int p; //下一个数据写入位置
int q; //下一个数据读出位置
int size; //缓冲区的总字节数
int free; //缓冲区的空闲字节数
int flags; //记录缓冲区是否溢出
struct TASK *task; //当队列缓冲区写入数据时需要唤醒的任务
};
相关操作函数
//缓冲区初始化函数
void fifo32_init(struct FIFO32 *fifo, int size, int *buf, struct TASK *task)
{
fifo->size = size;
fifo->buf = buf;
fifo->free = size;
fifo->flags = 0;
fifo->p = 0; //下一个数据写入位置
fifo->q = 0; //下一个数据读出位置
fifo->task = task;
return;
}
//缓冲区写入函数
int fifo32_put(struct FIFO32 *fifo, int data)
{
//如果缓冲区已满
if (fifo->free == 0)
{
fifo->flags |= FLAGS_OVERRUN;
return -1;
}
fifo->buf[fifo->p] = data;
fifo->p++;
if (fifo->p == fifo->size)
{
fifo->p = 0;
}
fifo->free--;
//如果有需要唤醒的任务
if (fifo->task != 0)
{
//如果任务处于休眠
if (fifo->task->flags != 2)
{
task_run(fifo->task, -1, 0);
}
}
return 0;
}
//缓冲区读出函数
int fifo32_get(struct FIFO32 *fifo)
{
int data;
//缓冲区为空 没有数据可读
if (fifo->free == fifo->size)
{
return -1;
}
data = fifo->buf[fifo->q];
fifo->q++;
if (fifo->q == fifo->size)
{
fifo->q = 0;
}
fifo->free++;
return data;
}
简单来说就是在一块缓冲区上,有一个指针指向写入的地址,一个指针指向读取的地址,如果写入满了,则该写入的数据会被丢弃。
从而形成一个IO环。
代码和原理是比较简单的。
但是解决的问题却是不简单的。
在这里主要解决了两个问题:
鼠标中断数据的处理
因为中断函数的特殊性,中断中不能处理过多事情,比如说在鼠标中断的时候,就会将鼠标的数据(移动,按键信息)直接塞进FIFO结构体,然后就退出中断处理函数。
等待到内核线程调度的时候自行读取FIFO中的数据,操作显存移动鼠标,窗体等等操作。
这样的好处是,即使中断频繁发生,内核线程都无力处理的时候,顶多会丢弃一些数据,但不会影响系统正常运行。
进程/线程间消息通讯
现在的设计是每个线程都有自己的一个FIFO结构体用于存在通讯消息。
向线程发送消息就是向该进程FIFO结构体写入数据。
等该线程有执行机会的时候,自行读取处理,这样这个系统的设计都是基于消息的异步通知机制,和现代的操作系统思想设计一致。
发表评论
要发表评论,您必须先登录。