0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

rt-smart select的实现

冬至子 来源:HAHABO 作者:HAHABO 2023-08-09 16:05 次阅读

select介绍

select()是常用的多路IO复用的posix调用接口。select () 函数指示指定的文件描述符中的哪些已准备好读取、准备好写入或有待处理的错误条件。如果指定的条件对于所有指定的文件描述符都为假, 则 select() 阻塞,直到发生超时或直到指定的条件对于至少一个指定的文件描述符为真。

rt-smart select的实现

rt-smart是一个包含用户层内核层包含MMU硬件功能的OS,用户层发送的系统调用请求,会通过特定的指令使cpu陷入异常,并进行相应的异常处理,其中用户态的select函数最终会调用lwp_syscall.c中的sys_select函数。sys_select函数会调用rt-smart的虚拟文件系统dfs实现的select函数(所在文件)。而select函数则会调用rt-smart的虚拟文件系统dfs实现的poll函数(所在文件)。

int poll(struct pollfd *fds, nfds_t nfds, int timeout)
{
int num;
struct rt_poll_table table;
poll_table_init(&table);
num = poll_do(fds, nfds, &table, timeout);
poll_teardown(&table);
return num;
}

这里会首先初始化一个poll的表,然后调用poll_do函数。

static void poll_table_init(struct rt_poll_table *pt)
{
pt->req._proc = _poll_add;
pt->triggered = 0;
pt->nodes = RT_NULL;
pt->polling_thread = rt_thread_self();
}
poll_table_init中将table的triggered设置为了0.

关于poll_do的函数解释,写在了函数注释中。

static int poll_do(struct pollfd *fds, nfds_t nfds, struct rt_poll_table *pt, int msec)
{
while (1)
{
pf = fds;
num = 0;
for (n = 0; n < nfds; n ++)
{
/ do_pollfd函数会调用对应的设备节点的poll回调函数 /
ret = do_pollfd(pf, &pt->req);
if(ret < 0)
{
/*dealwith the device return error -1 */
pt->req._proc = RT_NULL;
return ret;
}
else if(ret > 0) / 如果返回值大于0,num计数增加 /
{
num ++;
pt->req._proc = RT_NULL;
}
pf ++;
}
pt->req._proc = RT_NULL;
/ 如果num大于0或istimeout不为0则跳出循环 /
if (num || istimeout)
break;
/ 如果poll_wait_timeout返回值大于0则标记为超时,之后会再调用do_pollfd,但是无论do_pollfd的结果如何最终由于istimeout不为0,都会导致循环退出 /
if (poll_wait_timeout(pt, msec))
istimeout = 1;
}
return num;
}
static int poll_wait_timeout(struct rt_poll_table *pt, int msec)
{
if (timeout != 0 && !pt->triggered)
{
if (rt_thread_suspend_with_flag(thread, RT_INTERRUPTIBLE) == RT_EOK)
{
rt_hw_interrupt_enable(level);
rt_schedule();
level = rt_hw_interrupt_disable();
}
}
ret = !pt->triggered; / 这个值会在wakeup中被修改 /
rt_hw_interrupt_enable(level);
return ret;
}

wait函数在中途会调用 rt_schedule()触发系统调度,当前线程被切回来以后会检查pt->triggered的值来确定函数的返回值。

poll函数的实现
int test_dev_poll(struct dfs_fd *fd, struct rt_pollreq *req)
{
/ 这里的waitqueue是设备节点dev中的waitqueue /
rt_poll_add(waitqueue, req);
if(is_sould_return)
return POLLIN | POLLRDNORM;
return 0;
}

这个函数的逻辑是当设备节点的poll函数回调被调用时,需要看一下此时有没有数据可以让用户态去读取,而这个有没有数据的信息需要驱动自己维护。如果有的话就返回非0的值,如果没有的话就直接返回0。

而rt_poll_add(waitqueue, req);会挂载一个req资源到waitqueue中,如果有人唤醒了这个队列,那么前面的poll_wait_timeout就会被唤醒。rt_poll_add会调用req的_proc函数,这个函数在前面的poll_table_init中被赋值为了_poll_add。

static void _poll_add(rt_wqueue_t *wq, rt_pollreq_t *req)
{
node->wqn.key = req->_key;
rt_list_init(&(node->wqn.list));
node->wqn.polling_thread = pt->polling_thread;
node->wqn.wakeup = __wqueue_pollwake;
node->next = pt->nodes;
node->pt = pt;
pt->nodes = node;
rt_wqueue_add(wq, &node->wqn);
}

这里比较重要的是node->wqn.wakeup被赋值为了__wqueue_pollwake。之后队列唤醒的时候这个回调函数会被调用。

void rt_wqueue_wakeup(rt_wqueue_t *queue, void *key)
{
if (!(rt_list_isempty(queue_list)))
{
for (node = queue_list->next; node != queue_list; node = node->next)
{
entry = rt_list_entry(node, struct rt_wqueue_node, list);
if (entry->wakeup(entry, key) == 0)
{
rt_thread_resume(entry->polling_thread);
need_schedule = 1;
rt_wqueue_remove(entry);
break;
}
}
}
}

wakeup函数用于唤醒一个正在因队列等待而休眠的线程,该函数会去查找entry的wakeup回调函数,这个回调函数就是前面提到的__wqueue_pollwake。

static int __wqueue_pollwake(struct rt_wqueue_node *wait, void *key)
{
struct rt_poll_node *pn;
if (key && !((rt_ubase_t)key & wait->key))
return -1;
pn = rt_container_of(wait, struct rt_poll_node, wqn);
pn->pt->triggered = 1;
return __wqueue_default_wake(wait, key);
}

__wqueue_pollwake函数最终将triggered置位了1,代表poll_wait_timeout被wakeup的话,其返回值就是0。poll_do函数由于循环的原因会再次调用poll函数。

那么rt_wqueue_wakeup这个函数,在正常的设备驱动中一般就由中断函数来调用,如果中断函数代表有数据需要应用层读取处理的话。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 处理器
    +关注

    关注

    68

    文章

    18278

    浏览量

    222166
  • 驱动器
    +关注

    关注

    51

    文章

    7308

    浏览量

    142968
  • 触发器
    +关注

    关注

    14

    文章

    1677

    浏览量

    60404
  • MMU
    MMU
    +关注

    关注

    0

    文章

    91

    浏览量

    17943
  • 串口中断
    +关注

    关注

    0

    文章

    63

    浏览量

    13608
收藏 人收藏

    评论

    相关推荐

    通过Uboot TFTP启动rt-smart内核

    介绍Windows下通过 Uboot  TFTP 方式下载和启动rt-smart 内核
    的头像 发表于 06-30 12:34 3157次阅读
    通过Uboot TFTP启动<b class='flag-5'>rt-smart</b>内核

    RT-Smart的资料合集

    1、RT-Smart的启动过程在熟悉 RT-Smart 架构的过程中,研究其启动过程的是必不可少的,那么在系统正常运行之前,需要做哪些准备工作呢。本文将以 32 位 RT-Smart 的源代码为
    发表于 03-22 15:06

    rt-smart中断阻塞问题是怎么引起的

    rt-smart 中断阻塞问题如何解决?该问题是怎么引起的?为了测试rt-smart的实时性,测试了一下中断的稳定性。用systick的1ms中断做测试源。平时都正常的,但是发现打印时,波形老是抖动
    发表于 03-25 09:56

    请问rt-smart gdbserver是闭源的吗?

    编译“RT-Smart”,启用RT_USING_GDBSERVER时,发现许多文件都找不到,请问这部分代码不公开吗?比如#include #include
    发表于 04-19 09:37

    请问rt-smart gdbserver是闭源的吗?

    编译“RT-Smart”,启用RT_USING_GDBSERVER时,发现许多文件都找不到,请问这部分代码不公开吗?比如#include #include
    发表于 04-26 10:01

    基于RT-Thread操作系统衍生rt-smart实时操作系统简介

    1、rt-smart 实时操作系统简介RT-Thread Smart(简称 rt-smart)嵌入式实时操作系统是基于 RT-Thread
    发表于 06-22 17:56

    rt-smart应用程序系统调用实现过程是怎么样的?

    rt-smart应用程序系统调用实现过程是怎么样的? 比如open时候怎么一步一步切换到内核态的?
    发表于 09-08 17:00

    rt-smart中的imx6ull用户态点灯

    rt-thread的rt-smart已经发布有段时间了,其实我之前也写过几篇关于rt-smart的文章,但是都是关于CMake构建工程的文章。 而对我来说一直想在用户态操作一下底层硬件的东西。而在
    的头像 发表于 01-15 13:41 2550次阅读
    <b class='flag-5'>rt-smart</b>中的imx6ull用户态点灯

    树莓派上rt-smart的应用编程入门

    我们从现在开始会逐步连载RT-Thread Smart(简称rt-smart,甚至有时会称为smart os)的介绍文章,旨在让大家认识,接触到sm
    的头像 发表于 05-13 14:10 2712次阅读
    树莓派上<b class='flag-5'>rt-smart</b>的应用编程入门

    rt-smart移植分析:从树莓派3b入手

    移植rt-smart到最新的板子上具体需要注意哪些细节,哪些才是移植rt-smart的关键点?本文从树莓派3b上移植rt-smart的角度,从头分析rt-sm...
    发表于 01-25 18:48 0次下载
    <b class='flag-5'>rt-smart</b>移植分析:从树莓派3b入手

    优雅的在D1S上运行RT-Smart

    前言 最近在学习 RT-Smart ,正巧有在全志开发者论坛看到这么一篇帖子【惊】在麻雀上运行国产rt-smart系统,看到很多人都在关注 D1S 在 Smart 上的运行情况。如今该 BSP 已经
    的头像 发表于 11-16 20:15 1911次阅读

    丝滑的在RT-Smart用户态运行LVGL

    开发流程 1、RT-Smart 环境搭建 下载 RT-Smart 用户态应用代码: 1 git clone https: //github.com/RT-Thread/userapps.git
    的头像 发表于 11-22 20:20 939次阅读

    RT-Smart riscv64汇编注释

    rt-smart在全志D1上的代码为例,主要注释了rt-smart在riscv64上的系统初始化和异常处理的代码仓库地址https://gitee.com/rtthread/rt
    的头像 发表于 02-08 21:40 808次阅读

    零基础上手rt-smart适配bsp

    RT-Thread Smart(简称rt-smart)是基于RT-Thread操作系统衍生,面向带MMU(Memory Management Unit),中高端应用的芯片,例如ARM
    的头像 发表于 08-08 10:34 591次阅读
    零基础上手<b class='flag-5'>rt-smart</b>适配bsp

    RT-Smart riscv64汇编注释

    rt-smart在全志D1上的代码为例,主要注释了rt-smart在riscv64上的系统初始化和异常处理的代码
    的头像 发表于 10-12 17:26 340次阅读
    <b class='flag-5'>RT-Smart</b> riscv64汇编注释