首页 > 安全资讯 >

41.内核链表状态机多线程编译器

16-09-30

41 内核链表状态机多线程编译器

41.1.linux内核链表

(1)实际实际项目中的链表节点中存储的数据其实是1个结构体,该结构体中包含若干的成员,这些成员加起来构成了节点数据区域;因为链表实际解决的问题是多种多样的,所以内部数据区域的结构体构成也是多种多样的,则导致不同程序当中的链表总体构成是多种多样的;我们无法通过1个泛性的/普遍适用的操作函数来访问所有的链表;则我们每设计1个链表就得写1套链表的操作函数;不同的链表的操作方法不能通用需要单独写,但是实际上内部的思路和方法是相同的,只是函数的局部地区有不同,即涉及到数据区域的操作不同。

(2)我们的目的即把所有链表中操作方法里共同的部分提取出来用1套标准方法实现,然后把不同的部分留着让具体链表的实现者自己去处理;内核链表中自己实现了1个纯链表(纯链表就是没有数据区域,只有前后向指针)的封装,以及纯链表的各种操作函数,该纯链表本身没有任何用处,它的用法是给我们具体链表作为核心来调用。

(3)内核中核心纯链表的实现在include/linux/list.h文件中;list.h中就是1个纯链表的完整封装,包含节点定义和各种链表操作方法。

(4)内核链表中的使用方法是将内核链表节点作为将来整个数据结构的结构体的1个成员内嵌进去;我们可以通过操作结构体的某个成员变量来操作整个结构体变量,这里面要借助container_of宏。

41.2.什么是状态机

(1)常说的状态机是有限状态机FSM(有限个状态,该状态通常是表示1个状态变量的值);该状态机器同时能够从外部接收信号和信息输入,然会该机器会综合考虑当前自己的状态和用户输入的信息,然后机器做出动作跳转到另1个状态;考虑状态机的关键点是当前状态+外部输入+下1个状态。

(2)两种状态机=Moore型+Mealy型;Moore型状态机的输出只与当前状态有关(与输入信号无关),相对简单,考虑状态机的下1个状态时只需要考虑它的当前状态就行了;Mealy型状态机的输出和当前状态+输入信号有关,状态机接收到某个输入信号需要跳转到下1个状态时,状态机需综合考虑2个条件(当前状态+输入值)后才决定跳转到哪个状态。

(3)状态机的主要用途=电路设计(电路设计中广泛使用了状态机思想)+FPGA程序设计+软件设计(框架类型的设计,譬如操作系统的GUI系统和消息机制)。

(4)我们平时写程序都是顺序执行的,该类程序的大体执行流程是既定的,程序的执行是遵照一定的大的方向有迹可寻的;但有时候外部不一定会按照既定流程来给程序输入信息,而程序还需要完全能够接收并响应外部的这些输入信号,还要能做出符合逻辑的输出,这时候就应该使用状态机。

(5)C语言实现简单的状态机=开锁状态机,用户连续输入正确的密码则会开锁,如果密码输入过程错误则锁会退回到初始状态重新计入密码,用户只需要连续输入出正确的密码即可开锁(输入错误不用撤销也不用删除)。

41.3.多线程简介

(1)操作系统下的并行执行机制;并行就是说多个任务同时被执行,并行分微观上的并行和宏观上的并行;宏观上的并行就是从长时间段(相对于人来说)来看,多个任务是同时进行的;微观上的并行就是真的在并行执行;操作系统要求实现宏观上的并行,第1种是微观上的串行,第2种是微观上的并行。

(2)理论来说,单核CPU本身只有1个核心,同时只能执行1条指令,该类CPU只能实现宏观上的并行,微观上一定是串行的;微观上的并行要求多核心CPU,多核CPU中的多个核心可以同时微观上执行多个指令,因此可以达到微观上的并行,从而提升宏观上的并行度。

(3)进程和线程的区别和联系;进程和线程是操作系统的两种不同软件技术,目的是实现宏观上的并行(通俗一点就是让多个程序同时在一个机器上运行,达到宏观上看起来并行执行的效果);进程和线程在实现并行效果的原理上不同,而且该差异和操作系统有关,譬如windows中进程和线程差异比较大,在linux中进程和线程差异不大(linux中线程就是轻量级的进程);不管是多进程还是多线程,最终目标都是实现并行执行。

(4)多线程的优势;前些年多进程多一些,近些年多线程开始用得多;现代操作系统设计时考虑到了多核心CPU的优化问题,保证了多线程程序在运行的时候,操作系统会优先将多个线程放在多个核心中分别单独运行,则多核心CPU给多线程程序提供了完美的运行环境,那么在多核心CPU上使用多线程程序就有极大的好处。

(5)多线程程序运行时要注意线程之间的同步(多线程同步和锁)。

41.4.编程工作的演进史

(1)CPU需要的只是1和0组成的二进制数据;不管编程怎么变,最终编程得到的可执行二进制程序都是给CPU运行的,CPU需要的只是按照CPU设计时的规律(机器指令)排布的1串二进制1和0组成的数字(机器码),CPU根本不关心这些二进制是怎么来的;这些二进制可能是1个很厉害的程序员直接用1和0拼出来的,也可以是用汇编语言编写最终编译得到的,也可以是用C语言编写最终编译得到的;也可以是用java/C#/php/bash等语言编写然后解释得到的;编程工作的演进其实一直是在处理上一个层次段落即使用何种语言编写程序(用某种语言进行编程),然后如何把这种程序源代码转成二进制(编译器的发明);CPU接收到1串1010序列后如何工作达到目的,这就是设计制造CPU的公司要考虑的事情了,与软件工程师完全无关。

(2)早期的纸卡打孔编程者;最早期的时候,CPU也很简单,指令集很少,二进制位数也不多,那时候编译器也没被发明,编程语言也没被发明,那时候就是用二进制直接编程的;最早的编程没有语言也没有编译器,程序员直接使用二进制和机器(CPU)对话;这种方式的坏处就是不容易扩展,随着CPU的进一步复杂化,指令的变多,指令位数的变多,编程难度呈几何倍数增长,人的大脑慢慢就跟不上这个节奏。

(3)编程工作的第1次革命即由二进制机器码到汇编语言;人类发明了汇编语言,汇编语言的本质就是用1个符号来代替1串二进制;有了汇编语言之后,程序员就不用再去记忆二进制序列了,编程时只需要用汇编指令来编程即可,汇编指令就是1个符号(符号就是由文字构成的如MOV),因为人类大脑天生对文字符号更加友好,因此用符号编程更简单;用汇编语言编写的源程序不能直接给CPU运行,必须通过1个翻译过程,把源代码翻译成二进制序列才能给CPU,这个翻译的过程就叫汇编,执行翻译动作的就是汇编器。

(4)编程工作的第2次革命即由汇编语言到C语言;汇编语言也有一些不尽如人意的地方,譬如没有可移植性,在这个CPU上写的汇编程序无法直接在另一个CPU上运行,因此汇编语言是和CPU一一对应的;为了可移植性于是乎发明了高级语言,第1个高级语言就是C语言,C语言进一步靠近人的思维,为人的思维发明了很多CPU没有的东西,譬如数组,最终的目的就是降低编程难度,让高级语言更接近人的思维,然后通过编译器+汇编器等的翻译将这些源代码变成二进制然后给CPU运行。

(5)革命无穷尽+层次变更多;在C语言之上还有更高级语言,譬如C++/Java/C#/bash等,越往上越靠近人的思维,越往上语言本身提供的封装越多,越往上编程难度越低,语言的掌握越容易。

41.5.程序员编译器CPU之间的关系

(1)CPU只认识二进制机器指令;人类的大脑本身不喜欢二进制而喜欢符号和文字,人类和机器之间天生有代沟,于是乎编程不容易。

(2)连接人(程序员)与机器(CPU)的桥梁是编译器;编译器降低了编程难度,编译器的代表就是编程语言,每1种编程语言都有对应的编译器,该编译器的作用就是把这种语言的源文件编译成可执行程序;有了编译器(高级语言)之后,我们程序员就不再盯着CPU(二进制),而是改为盯着编译器(编程语言及编程语言的语法),所以我们学习编程的关键变成了学习编译器的习性,即编程语言的语法。

(3)发明一门语言关键就在于发明它的编译器;编译语言的关键就是编译器,yacc和lex工具就是用来发明编程语言的;高级语言与低级语言的差别即越高级的语言越靠近人类思维,越低级的语言越靠近机器的需要;人与机器总劳动量(总复杂度)守恒,人要是复杂一点机器就可以简单一点,人简单一点机器就需要复杂一点;该规律描述的就是编程语言越简单,人使用起来越简单,编译器设计起来就更复杂;编程语言越复杂,程序员使用起来越麻烦,则编译器设计越简单,CPU执行效率越高。

41.6.像编译器一样思考吧

(1)语法是什么,语法就是编译器的习性,编译器反应在编程中就是语法(!!i;该语句的作用是若i为0则返回0,若i为非0则返回1);习得1门语言就像认识1个朋友,从新的开始认识1个人到成为好朋友,这里面要经历时间+共事;学习1门编程语言也需要时间+实践(共事)。

(2)学习编程语言要懂得换位思考,譬如预处理中处理程序注释+空行是为了使得编译器专注于自己的工作即编译程序;注意实践中的摸索和总结(在实践中+摸索+总结)。


41.kernel_linked_list
/*
 * 公司:XXXX
 * 作者:Rston
 * 博客:http://blog.csdn.net/rston
 * GitHub:https://github.com/rston
 * 项目:内核链表状态机多线程编译器
 * 功能:演示内核链表的基本使用。
 */

#include 

// driver_info结构体用来存储驱动信息
struct driver_info
{
    int data;
};

// driver结构体用来管理内核中的驱动
struct driver
{
    char name[20];              // 驱动名称
    int id;                     // 驱动id编号
    struct driver_info info;    // 驱动信息
    struct list_head list;      // 内核链表节点
};

41.state_machine
/*
 * 公司:XXXX
 * 作者:Rston
 * 博客:http://blog.csdn.net/rston
 * GitHub:https://github.com/rston
 * 项目:内核链表状态机多线程编译器
 * 功能:使用C语言实现简单的状态机。
 */

#include 

// 给状态机定义状态集
typedef enum 
{
    STATE1,
    STATE2,
    STATE3,
    STATE4,
    STATE5,
    STATE6,
    STATE7,
}STATE;

int main(int argc, char **argv)
{
    int num = 0;

    // current_state记录状态机的当前状态
    STATE current_state = STATE1;       

    printf("请输入密码,密码正确开锁.\n");
    while (1)
    {
        scanf("%d", &num);

        switch (current_state)
        {
            case STATE1:
                if (num == 1)
                {
                    current_state = STATE2;     // 用户输入对了1步,STATE走1步
                }
                else
                {
                    current_state = STATE1;     // 用户输入错误,返回初始状态
                }
                break;
            case STATE2:
                if (num == 2)
                {
                    current_state = STATE3;     
                }
                else
                {
                    current_state = STATE1;
                }
                break;
            case STATE3:
                if (num == 3)
                {
                    current_state = STATE4;     
                }
                else
                {
                    current_state = STATE1;
                }
                break;
            case STATE4:
                if (num == 4)
                {
                    current_state = STATE5;     
                }
                else
                {
                    current_state = STATE1;
                }
                break;
            case STATE5:
                if (num == 5)
                {
                    current_state = STATE6;     
                }
                else
                {
                    current_state = STATE1;
                }
                break;
            case STATE6:
                if (num == 6)
                {
                    current_state = STATE7;     
                }
                else
                {
                    current_state = STATE1;
                }
                break;
            default:
                current_state = STATE1;
        }

        if (STATE7 == current_state)
        {
            printf("锁开了.\n");
            break;
        }
    }

    return 0;
}

相关文章
最新文章
热点推荐