大家好,我是兔子。
是一个嵌入式软硬件工程师。
正在从单片机开发转岗Linux开发。
上一节,我们使用gpio驱动将数码管扫描点亮。
这一节,我们再来控制数码管,使用多线程的概念,让数码管在不停的扫描的同时,还可以做其他的事情,比如计数。
1.操作大纲
1)使用第5节编写的gpio驱动,即gpio_driver.ko(i.MX283及i.MX287也一样,驱动配置稍微调整)。加载驱动。
2)更改上一节的数码管的程序,增加多线程并另外开一个线程,专门用来计数。让数码管每过1秒,显示的数字加1。
3)编译多线程之数码管程序。
4)开发板运行多线程之数码管,观看效果。
2.多线程概念
1)什么是线程
线程是CPU进行调度的基本单位。简单的来说,线程就是进程里面的进程,不过线程共享了进程的虚拟地址空间,而且公用了进程的代码段和数据段。
2)线程的优点
使多CPU系统更加有效。操作系统会保证当线程数不大与CPU数目时,不同线程运行于不同的CPU之上。
改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。
3)简述多线程
简单来说:CPU运行程序,都是按照程序顺序一步一步执行的。这样,如果遇到一个需要等待的地方,比如延时。CPU就会等待,进而就会阻塞住。影响后面的程序的实时性及执行效率。这时,如果将等待的这个时间,拿来执行其他的程序步骤。等到时间了,再跳回到上次等待的地方继续执行。不就把CPU的资源节约下来了么?
同理,有时候我想20毫秒的时间,来执行数码管的扫描功能。下个30毫秒,我想让CPU来执行ADC模拟采集功能。就算20毫秒数码管的程序没有执行完,或者执行了2~3遍了,都没关系。我可以模拟成中断的形式,到时间,将运行产生的临时数据存起来,等下次轮到该程序,再将运行的临时数据取出来还原现场。
比方说,到了规定的时间,让CPU的调度机制切换不同的任务,来实现将每个功能都运行起来而感觉不到有阻塞感(实时性)。
注意:Linux线程的调度不是通过定时来切换的。这里只是打个比方说明多线程的意义。因为Linux为非实时操作系统。
3.调整驱动及驱动编译
使用第5节编译好的gpio驱动gpio_driver.ko,直接在开发板上加载驱动即可。
(如果对gpio驱动不清楚的,可以移步教程5)
兔子MCU:从51单片机到Linux Linux操控流水灯(教程5)zhuanlan.zhihu.com需要通过NFS共享文件服务传输到开发板中加载。
(如果对NFS服务不清楚,可以移步教程3)
兔子MCU:从51单片机到Linux 开发板传文件利器-NFS(教程3)zhuanlan.zhihu.com4.修改程序
#include
程序说明:
1)添加头文件#include <pthread.h>
多线程操作专用。
2)pthread_t id_1;
为创建线程id,创建了1个id,为id_1
3)pthread_create(&id_1,NULL,(void *)thread_1,NULL);
创建线程的函数,程序初始化需要先创建线程。参数里需要填写线程id,以及线程执行的函数thread_1。
告诉内核,thread_1这个线程函数被创建了,对应的id为id_1。
4)static void thread_1(void)
为线程thread_1的操作函数,一般函数里是一个while(1) 的循环,也可以不是。
由linux内核对线程进行调度。while(1)里的程序,当linux内核需要调度时,会自动将运行产生的临时数据存储起来,切换到其他线程。等下次再切回到这个线程时,再恢复这些临时数据并继续运行。
5)程序的功能
根据程序,可以得知。一共有两个线程。一个是thread_1。专门用来1秒钟计数。将数据存到全局变量cnt里。
另一个线程为main函数里的while(1)大循环。专门用来进行数码管的动态扫描的。将线程thread_1计数的cnt显示在数码管上。
将程序命名为gpio_595_auto_calc.c。并修改Makefile文件。
然后使用终端,make一下,进行多线程程序的编译。
无错误和警告。
至此,数码管多线程程序编译完成。
5.运行程序
1)开发板上电,并挂载NFS共享目录。
(具体操作可移步教程3)
兔子MCU:从51单片机到Linux 开发板传文件利器-NFS(教程3)zhuanlan.zhihu.com2)进入开发板的NFS挂载点/mnt文件夹下。通过ls命令能查看到我们编译好的数码管多线程程序和驱动。
3)首先,先加载驱动。
使用insmod gpio_driver.ko指令。
可以看到,打印了很多生成的文件。表示驱动加载成功。
4)运行数码管多线程程序
使用./gpio_595_auto_calc & 表示让数码管多线程程序在后台运行。
至此,数码管多线程程序已经成功运行。