语言2.创造第二个驱动程序

小编先请各位看官原谅那难点,实在想不出更适合的。那个年因为工作提到,接触了好多对外中文教材。早就想吐槽市镇上那类教材中的无聊课文了。后天先说说那几个为国外学生在非粤语国(比如美利坚合众国上学的小孩子在美利哥)学习中文而编写制定的讲义。比如《真棒》、《汉语传闻读写》、《跟小编学普通话》等等

先讲解驱动框架,然后写出first_drv驱动程序,来打字与印刷一些新闻

一. 会话课文几时了,无聊知多少

        这几个年持续有新的对外中文化教育材上市,不过那类教材“同质”化
严重。比如,都分成多少个宗旨,种种宗旨都是课文为基本,课文超越50%是对话,而且便是稀松平日的对话。假若把某教材的一篇课文跟另一教科书中同样宗旨里的课文对换,除了人物名字差别,其余则毫无违和感。

       
课文以对话的花样出现本来有优势,尤其是在强调交流的见识下。不过,对话并非语言交换的唯一格局啊,更何况篇篇是对话,学生会发生审美疲劳。适当换一种文娱体育,比如记叙文娱体育的典故、可能快板、古典诗词等等,效果反而更好。而且学生能够依照内容,自身编写成对话,并不曾献身面对面口头调换的火候。

       
当然,最根本的还不是文娱体育单一,而是内容无聊。那一个课文假诺不是出新在对外中文教材中,相对不会有其它出版价值!从那些角度也足以见见,那类课文不属于“真实语言质感”。那和现代的外语教学理念、以及美外国语大纲的渴求是违反的。

        举三个例证,上边包车型大巴那篇课文出今后某本对外汉语教材中。

医师:你哪儿不舒服?

XXX:笔者鼻塞、胃痛,头也晕晕的。

医生:作者来量量你的体温。三十九度,你脑仁疼了。

XXX:很惨重吗?

大夫:不严重,只是头疼。你最幸而家休息几天。

XXX:供给注射吗?

先生:不用打针,吃药就行了。

XXX:一天要吃五遍药?

先生:一天壹次,叁回两粒。

XXX:作者还相应注意什么?

医师:多喝水,多吃点水果,过几天就好了。

       
以上正是课文的全部。那几个对话是一人看病时跟医务卫生人士的沟通,但只要把它作为课农学习,编者或然忘了3个实际:在国外学汉语的上学的小孩子去就诊时,他们的大夫一般不说中文,所以读书那样的内容并无实际用途!依照作者的这一个年的经验,那段对话中最实用的词正是“咳嗽、头痛、在家休息”,它们被用来在学生不可能来上课时给老师发的微信中。既然如此,还不如直接编1个师资和学习者关于请病假的对话,何必到医师那里“拐个弯儿”呢?在华夏深造粤语的异域学生由于实在生活的内需,对看病、租房的话题感兴趣,他们把生活必要变成学习重力。可是在国外学习粤语的学习者则并未这么些引力。

       
既然无法学以致用,还要让学生愿意地读书相应的词汇、语法,那大家就得给学员2个除了看病以外的“吸睛点”,从而激励她们的就学热情。遗憾的是,那篇课文没有到位。类似那样的课文,不少教员职员员师和学生都觉着味同嚼蜡。学生学得无精打采,在班上表演这一个对话时也提不起兴趣。作者还见过一篇介绍中国的现代化学医高校的课文(不记得出自哪个教材了),即使不是对话,但是就干Baba地列出了华夏现代化的医院近来能够提供的劳动,比如B型超声诊断,X光,CT等等。读此课文真是令人昏昏欲睡,堪比催眠!

写出first_drv驱动程序须求以下几步:

二. 投石问路话“解药”

       
怎么着让课文不再无聊啊?作者信任办法有这几个。自媒体节目《罗辑思维》有一句口号:有种、有趣、有料。作者觉着治疗无聊课文的解药也是那八个“有”,但要把各种变变:有趣、有料、有种。

     
 “有趣”最好掌握。“有料”是指内容提到科学、技术、工程、艺术和数学等其它学科的知识,相比符合米利坚新近风行的STEAM教学大纲。“有种”跟延续祖宗门户没有涉及,字典上的趣味是“有气魄,有胆量”,对于课文来说,是指这一个“不怕引起争议”的篇章。比如《田期思赛马》这样的故事就是有料又有种。传说不仅关乎可能率学、博弈论的学识,而且田期思的做法也值得钻探,甚至不难招惹争议(田期思是还是不是服从了平整、什么才是理所当然规则、中夏族民共和国人有没有“契约精神”、等等)。个人认为那样的争执并非坏事,反而能构建学生施用审辩思维(critical
thinking)的能力。

       
最不难实现的是“有趣”,在初级教材中就足以,而“有料”和“有种”的课文恐怕更符合中、高级的读本。前些天自身就以那些“有趣”为题展开座谈。还是以地点那篇课文为例,请看上边那么些改编版:

爸爸下班回家,看到外孙子小明躺在床上。小明说,他鼻塞、胃痛、头也晕晕的。老爸立时带小明去了诊所。医务人士给小明量了体温,36度,不发咳嗽。医务人士对小明说:“你也许只是胃痛,不用打针,吃点药就行了,这几个药一天三次,2次两粒。”然而小明说:“医务卫生人士,笔者觉着很不爽快,前几天亟需在家休息,您给本身写个假条吧。”父亲也说:“是呀,最幸而家休息一天。”医务职员对老爸说:“他的胸口痛不严重,多喝水,多吃点水果,过几天就好了。前天能够去学习。”正在此时,小明收到一条微信,是他的国语老师发的,告诉她明日的国语考试改在后天了。小明马上对医务卫生人士说:“您说得对,笔者前些天不须求在家休养,可是小编后天必要啊。”

       
那些改编版和旧版课文比较,没有献身旧版的词汇和语法点,也尚无拉长很多新词和新语法点,可是结尾处的“神转折”
却让学员们觉得课文不再枯燥了、有意思了,他们读到最终时会发出各个笑。学生觉得有意思,就愿意把它改写成对话来表演。说实话,让学员把旧版对话改写成有趣的遗闻难,因为他们凭空想不出“神转折”式的最后;可是把改编版改写成贰个会话却不难;而且受其启发,还是能“添枝加叶”。有的学员就续编新结尾,比如这么些微信其实是阿爸让教授发的、想看看小明是还是不是装病,“让转账尤其转折”(引自Papi酱)。

        笔者原先观摩过一堂中文课,老师在课堂上用TPXC90S(Teaching Proficiency
through Reading and
Storytelling)教学法,极力启发学生的想象力、指点学员编遗闻。这么些改编版其实就起到了启示和指导的效率。如若翻看这几个学生感兴趣的课文,共同点之一正是能指导、启发学生,像是七个隐蔽的TP哈弗S老师。


        再举一例。上边那篇微型随笔是自小编近年在微信里见到的,稍做了变动:

一个人长辈发现本人的双脚突然变成深红,心里不安。外甥看到后立刻请假送她去医院。医务卫生职员先列出三个清单,让老人去做检查:血液,心电图、脑电图、CT、核磁共振、B超等等。那个检查花了近万元。然后,医务卫生人士和口腔科专家会诊,最后诊断:
袜子掉色。

       
那篇小小说让自己纪念了那篇介绍中华夏族民共和国的现代化学医大学的课文。它在那之中的词汇也包含了CT、B型超声诊断等词汇,但却多了一个结尾恶作剧式的结尾,变成了小笑话。而且那是地地道道的“真实语言材料”,作为课文难道不是更行吗?


       
举那四个例子,并不是说每篇课文都要有“神转折”式的最终,而是想注脚,让课文变得不再无聊并简单,而且形式众多,然而需求教材的编辑们不拘泥古板,放飞思路、开阔眼界!只要做到那么些,笔者深信在不捐躯教学语言点、知识点的前提下,让教材的课文变得振奋人心是全然能够兑现的。

(1)写出驱动程序first_drv_open
first_drv_write

(2)须要定义file_operations结构体来封装驱动函数first_drv_open
first_drv_write

对于字符设备来说,常用file_operations以下多少个成员:

语言 1

(3)  模块加载函数,通过函数
register_chrdev(major, “first_drv”, &first_drv_fops) 来

注册字符设备

(4)写驱动的first_drv_init 入口函数来调用那些register_chrdev()注册函数,

(5)通过module_init()来修饰入口函数,使基础知道有那几个函数

(6)写驱动的first_drv_exit出口函数,调用那一个unregister_chrdev()函数卸载,

(7)
通过module_exit()来修饰出口函数

(8) 模块许可证申明,
最普遍的是以MODULE_LICENSE( “GPL v2” )来声明

1.首先创造first_drv.c文件

代码如下:

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/fs.h>

#include <linux/init.h>

#include <linux/delay.h>

#include <asm/irq.h>

#include <asm/arch/regs-gpio.h>

#include <asm/hardware.h>

#include <asm/uaccess.h>

#include <asm/io.h>


/*1写出驱动程序first_drv_open first_drv_write */

/*  inode结构表示具体的文件,file结构体用来追踪文件在运行时的状态信息。*/

static int first_drv_open(struct inode *inode, struct file  *file)
{
   printk(“first_drv_open\n”);      //打印,在内核中打印只能用printk()
   return 0;
}

/*参数filp为目标文件结构体指针,buffer为要写入文件的信息缓冲区,count为要写入信息的长度,ppos为当前的偏移位置,这个值通常是用来判断写文件是否越界*/

static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
  printk(“first_drv_write\n”);      //打印,在内核中打印只能用printk()
   return 0;
}


/*2定义file_operations结构体来封装驱动函数first_drv_open first_drv_write */

 static struct file_operations first_drv_fops = {
    .owner  =   THIS_MODULE,     //被使用时阻止模块被卸载
    .open   =   first_drv_open,      
    .write   =   first_drv_write,   
  };



/*4写first_drv_init入口函数来调用这个register_chrdev()注册函数*/
int first_drv_init(void)
{
   /*3 register_chrdev注册字符设备,并设置major=111*/
  /*如果设置major为0,表示由内核动态分配主设备号,函数的返回值是主设备号*/
register_chrdev (111, “first_drv”, &first_drv_fops); //111:主设备号,”first_drv”:设备名
/*
register_chrdev作用:在VFS虚拟文件系统中找到字符设备,然后通过主设备号找到内核数组里对应的位置,最后将设备名字和fops结构体填进去
*/
   return 0;
}

/*5 module_init修饰入口函数*/
module_init(first_drv_init);


/*6 写first_drv_exit出口函数*/
void first_drv_exit(void)
{
unregister_chrdev (111, “first_drv”);  //卸载驱动,只需要主设备号和设备名就行 
}

/*7 module_exit修饰出口函数*/
module_exit(first_drv_exit);

/*8许可证声明, 描述内核模块的许可权限,如果不声明LICENSE,模块被加载时,将收到内核被污染 (kernel tainted)的警告。*/
MODULE_LICENSE( "GPL v2" );

2然后写Makefile编译脚本:

KERN_DIR = /work/system/linux-2.6.22.6   //依赖的内核目录,前提内核是编译好的


all:                                
       make -C $(KERN_DIR) M=`pwd` modules   // M=`pwd`:指定当前目录

                                             // -C $(KERN_DIR)表示要用到依赖的目录里的Makefile

                                        // modules:要编译的目标文件
  
clean:
       make -C $(KERN_DIR) M=`pwd` modules clean
       rm -rf modules.order


obj-m      += frist_drv.o     //obj-m:内核模块文件,指将myleds.o编译成myleds.ko

3.
make,编写翻译生成frist_drv.ko文件

 语言 2

4.然后开发板通过nfs互联网文件系统来加载frist_drv.ko

加载在此以前率先通过 cat
/proc/devices来查看字符主设备号111是还是不是被占用

 语言 3

然后经过 insmod first_drv.ko来挂载, 通过 cat
/proc/devices就能见到first_drv已挂载好

 语言 4

5.经过测试程序测试frist_drv模块

测试程序first_driver_text.c代码如下

#include <sys/types.h>    //调用sys目录下types.h文件
#include <sys/stat.h>      //stat.h获取文件属性
#include <fcntl.h>
#include <stdio.h>

/*输入”./first_driver_text”,     agc就等于1, argv[0]= first_driver_text  */
/*输入”./first_driver_text on”,   agc就等于2, argv[0]= first_driver_text,argv[1]=on;  */

int main(int argc,char **argv) 
{
int fd1, fd2;
int val=1;
fd1 = open("/dev/xxx",O_RDWR);  //打开/dev/xxx设备节点
if(fd1<0)                   //无法打开,返回-1
  printf("can't open%d!\n", fd1);
else
   printf("can open%d!\n", fd1);    //打开,返回文件描述符

write(fd1, &val, 4);              //写入数据1
return 0;
}

6.然后arm-linux-gcc
-o first_driver_text first_driver_text.c生成执行文书

回到板子串口上使用./first_driver_text来运转,发现只要open()打不开,会回去-1

 语言 5

是因为大家尚无创建dev/xxx这么些装置节点,然后大家来创建,使它相当刚刚挂载好的first_drv模块

mknod -m
660 /dev/xxx c 111 0            //
first_drv模块的主设备号=111

./first_driver_text

 语言 6

结果如上海体育场合,发现测试程序里的open()函数调用了驱动中的first_drv_open()

write()函数调用了驱动中的first_drv_write(),

中间open()函数再次回到值为3,是因为描述符0,1,2都已经被控制台占用了,所以从3发端

7.创新底层驱动,使用动态装载:

除去静态装载驱动外,还足以动态装载,让系统自动为大家驱动装置自动分配设备号

7.1
修改first_drv_init入口函数和first_drv_exit 出口函数:

代码如下:

int major;              //定义一个全局变量,用来保存主设备号
int first_drv_init(void)
{
 /*设置major为0,由内核动态分配主设备号,函数的返回值是主设备号*/
  major =register_chrdev (0, “first_drv”, &first_drv_fops);  
  return 0;

}

void first_drv_exit(void)
{
unregister_chrdev (major, “first_drv”);  //卸载驱动, 将major填入即可
}

 

一般来说图,通过动态分配得出它的主设备号是252,然后重创252的测试程序

 语言 7

rm dev/xxx

mknod -m 660 /dev/xxx c
252 0

./first_driver_text

 语言 8

7.2
每一遍都要手工创建设备节点,大家自然也会认为这么做太费事了。

能够选拔机关创建设备节点,Linux有udev、mdev的机制,而笔者辈的A冠道M开发板上移植的busybox有mdev机制,然后mdev机制会通过class类来找到相应类的驱动装置来机关创立设备节点
(前提要求有mdev)

在哪个地方设置了mdev机制?

营造根文件系统之使用里有介绍

7.3 接下去使用insmod自动创建设备节点,
rmmod自动打消设备节点

(1)首先创设贰个class设备类,class是叁个设施的高等级视图,它抽象出低级的达成细节,然后在class类下,成立四个class_device,即类下面创建类的设施:(在C语言中class正是个结构体)

static struct class *firstdrv_class;               //创建一个class类
static struct class_device   *firstdrv_class_devs; //创建类的设备

 

(2)在first_drv_init入口函数中加上:

firstdrv_class= class_create(THIS_MODULE,"firstdrv");  

//创建类,它会在sys/class目录下创建firstdrv_class这个类


firstdrv_class_devs=class_device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"xyz");

//创建类设备,会在sys/class/firstdrv_class类下创建xyz设备,然后mdev通过这个自动创建/dev/xyz这个设备节点,            

 

 

(3)在first_drv_exit出口函数中拉长:

  class_destroy(firstdrv_class);                      //注销类,与class_create对应

  class_device_unregister(firstdrv_class_devs);      //注销类设备,与class_device_create对应

 

 重新编写翻译insmod后,会发未来/dev下自行的创始了xyz设备节点

 语言 9

其间在sys/class里有各品种的设施,
比如sys/class/fristdev下就有xyz

 语言 10

接下来mdv通过insmod xxx
就去class找到相应类的驱动装置来机关创设设备节点

为什么内容一变动,mdv就能自动运行创制设备节点吧?

是因为以前始建根文件系统时候,

在etc/init.d/rcS里添加了如此一段:

echo /sbin/mdev > /proc/sys/kernel/hotplug             //支持热拔插

然后kernel每当设备出现改变时,调用/sbin/mdev来拍卖相应的新闻,使mdev应用程序操作/dev目录下的装置,举行添加或删除

(4).再修改测试程序里open函数,将/dev/xxx改为/dev/xyz,那样就测试模块,就不供给再mknod了.

 驱动程序first_drv_open
first_drv_write中只是打字与印刷数据,接下去下一节便开头来点亮LED.

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图