IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 手写纯链表实现简易实时操作系统 -> 正文阅读

[数据结构与算法]手写纯链表实现简易实时操作系统

首先查找资料,发现没有这种写法,要不就是跑裸机,把各个外设初始化,然后进入while1中,执行各种计算,这是裸机系统,更高级一点的是使用了内部中断与外部中断,进行pc跳转,进入中断,返回的while1继续执行后续循环。
但是,这样的程序while中的逻辑与每个指令的调用次数的相同的,若有些计算不需要那么多的计算次数,而有些需要多次计算呢,解决办法是有的,有人会说,使用定时器中断啊,这确实是一个办法,但这种方式进行指针跳转,消耗的时间比较多,中断更适合进行一些flag标志类的触发条件,而系统大多是时间还是在while1中度过,我们使用的while1很多时间都是在延时中度过的,这样很不好,目前开源了很多实时操作系统,我看了一下,所有的属性已经封装好了,我们只需要调用封装好的函数和宏定义即可进行类如多线程的操作,比如32是单核cpu,跑的也像多核cpu一样,多个线程的while1极大提高了cpu的使用效率。
如果只是使用开源的代码进行使用,显然我是有些强迫症的,这个东西大佬们可以写出来,都是同行,我怎么就不可以呢,我也开始试着写一个属于我的操作系统,主要功能->实现对不同任务的等级不同,会自动分配该任务的执行时间,每个任务的时间是由自身在初始化时确定。

下面就是我的掉头发时间

首先,看一下我的主函数吧,是按照RTOS的样子仿照的

#include <stdio.h>
#include "list.h"
#include <stdio.h>
#include "cx_rtos.h"


int main()
{
    CX_RTOS_Init();

    Kernel_Start();

    printf("return 0\n");

    while(1)
    {
        //
    }
    return 0;
}

是不是感觉似曾相识呢,接下来是,初始化任务函数
主要思路为:由于linux内核使用了大量的链表,为了更加理解他的写作手法,进行仿制,linux系统开源了list.h的纯链表的函数与宏。首先创建一个纯链表,在创建一个线程任务链表,让任务链表包含纯链表,任务链表挂载任务函数

void CX_RTOS_Init(void)
{
    static create_list(name1,task1,10);//任务名称,任务函数,任务ID
    list_add_tail(&(name1.list),&Head);//插入任务,也就是插入链表

    static create_list(name2,task2,5);//任务名称,任务函数,任务ID
    list_add_tail(&(name2.list),&Head);

    static create_list(name3,task3,2);//任务名称,任务函数,任务ID
    list_add_tail(&(name3.list),&Head);

}

链表尾插也是使用的list.h文件函数
这里需要强调一下:是如何初始化一个链表的,是使用下面的宏来操作的,具体做法如下

/* 此代码的作用是初始化一个自定义名称的链表,把成员变量赋初值,并且将纯链表指向自己*/
/*链表节点*/
#define LIST_HEAD_NODE(name,address,value) { value,address, &(name.list), &(name.list) }

#define create_list(name,address,value) \
    struct node name = LIST_HEAD_NODE(name,address,value)

接下来是时间调度器函数,通过遍历纯链表,得到每个链表其所属于的结构体的地址,然后调用结构体内的函数指针,调用真正的函数

void Kernel_Start(void)
{
    struct node *pos;
    while(1)
    {

        for(int i = 0;i < MAX_ID;i++)
        {
            //遍历节点的函数指针所在地址的函数
            list_for_each_entry(pos,&Head,list){
                if(counter < pos->ID)
                {
                    printf("%d\n",pos->ID);
                    pos->pthread();
                }
            }
    /*计算出线程ID最大的数字,这将影响遍历结果,这个数字就是最大ID在整个轮询中调用的次数,也就是
     * 说,ID决定分子,所有ID的总数是分母,得到每个线程占用的时间的长短
     */
            counter++;

            if(counter > MAX_ID)
            {
                counter = 0;
            }
        }
    }
}

遍历结构体的根本是使用了下面的宏定义实现的功能。很强大

#define offsetof(TYPE, MEMBER)  ((size_t)&((TYPE *)0)->MEMBER)


/**
 * container_of - cast a member of a structure out to the containing structure 根据结构体重的一个成员变量地址导出包含这个成员变量mem的struct地址
 * @ptr:    the pointer to the member. 结构体变量中某个成员的地址
 * @type:   the type of the container struct this is embedded in. 结构体类型
 * @member: the name of the member within the struct.  该结构体变量的具体名字
 *
 */

#define container_of(ptr, type, member) ({                      \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type,member) );})

创建了链表,并且可以调度这个链表函数,现在和正常跑裸机是一摸一样的。如上面说的,让不同的函数执行不同的时间(不能让一个函数for循环的执行,执行完执行其他,这样会很脱节),每个函数又理解为不同的线程函数,
在遍历每个节点的时候,每个节点都有一个特定的ID,这个ID有两个作用,一个是确定该节点,另一个则是通过ID来计算时间,当遍历的一遍链表后,链表上所有节点的线程都会被执行,但若不想让某个线程执行呢,可以通过条件判断,遍历到该节点后,若ID大于一个特定值时则执行,小于则不执行,就可以控制遍历后,每个线程的调用次数,代码在上面Kernel_Start()中
此时,若有三个线程函数

void task1(void)
{
    printf("this is task1()...\n");
}
void task2(void)
{
    printf("this is task2()...\n");
}
void task3(void)
{
    printf("this is task3()...\n");
}

原理都是一个大的while1,里面有很多小的while1
执行
在这里插入图片描述
可以看到每个函数都被调用了,但是调用次数不同,这也就是我想要的结果啦

最后分享一下代码

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-10 14:44:49  更:2021-07-10 14:46:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 17:36:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码