|
本帖最后由 zyf1111 于 2023-11-12 01:14 编辑
继续进行比较基础的使用,这次是多线程。前面测试无论是LED操作还是按键响应,或者是**通信,其实都是一个进程,说白了就是一个主程序在运行,程序结束也就没了。引入多线程有什么意义呢?比如在进行**通信的时候,想要串口发送个数据,那如果是单线程,要么主动中断**通信去发发送串口数据,要么等到**程序运行完再去进行串口数据发送,无论怎样,都影响了当前事件的正常执行。如果使用多线程,可以粗略的认为能够同时进行两件事情互不耽误。至于多线程是如何调度的,那就要看看Linux内核相关的内容了。
还是继续使用CodeBlocks,Linux下一般使用pthread,算是引入了一个外部库,需要IDE里修改配置,告知链接器要到哪里找到哪个库。如下
多数时候都是靠理解去探索一个不熟悉的IDE的相关设置在哪里,如何填写,以上也是个人摸索测试的结果。
然后键入一些简单的实验代码。
- void* thread_1()
- {
- while(1)
- {
- printf("thread 1 run\n");
- sleep(1);
- }
- }
- void* thread_2()
- {
- while(1)
- {
- printf("thread 2 run\n");
- sleep(3);
- }
- }
- int main()
- {
- pthread_t th1;
- pthread_t th2;
- pthread_create(&th1,NULL,thread_1,NULL);
- pthread_create(&th2,NULL,thread_2,NULL);
- while(1)
- {
- sleep(10);
- }
- }
复制代码 创建两个线程,分别以1秒和3秒间隔打印字符串,也就是各自按不同频率做自己的事情。运行一下程序
可以看出基本上每三次线程1结束线程2才运行一次。当然事实上,这个打印的也不完全会以3:1的情况保持,大概是这样没错。想要更真切一点的效果。我们可以修改一下程序,把其中一个线程改为LED闪烁,这样,观察LED闪烁频率或者示波器观察下IO口波形更直观些。- void* thread_1()
- {
- static int i = 0;
- int led = open("/sys/class/leds/led-blue/brightness",O_RDWR);
- while(1)
- {
- if(i == 0)
- {
- i = 1;
- write(led,"1",1);
- }else{
- i = 0;
- write(led,"0",1);
- }
- sleep(1);
- }
- }
复制代码
这样写,保持了线程还是每秒一次执行的频率,每次会翻转一个IO口,实际观察后是比较准确的。 更近一步,添加个线程读取ADC,也是一样的写法。比较基础的应用就是这样子。再来一个比较实用的,那就是互斥锁。说到锁,其实在RTOS中也是有的,但RTOS和Linux又是另一种对比的事情了。
比如说,一个全局变量,在线程1中使用,但在线程2中也会用到,但同一时刻,只能一个线程去读写变量,所以加互斥锁来保护变量的确定性和准确度。做以下测试来深刻些。
相同频率的线程对同一变量进行操作,观察变量的值,比较容易看出区别。 - int aaa = 0;
- static pthread_mutex_t g_mutex_lock;
- void* thread_1()
- {
- static int i = 0;
- int led = open("/sys/class/leds/led-blue/brightness",O_RDWR);
- while(1)
- {
- pthread_mutex_lock(&g_mutex_lock);
- aaa += 1;
- pthread_mutex_unlock(&g_mutex_lock);
- printf("t1 a= %d\n",aaa);
- sleep(1);
- }
- }
- void* thread_2()
- {
- while(1)
- {
- pthread_mutex_lock(&g_mutex_lock);
- aaa -= 1;
- pthread_mutex_unlock(&g_mutex_lock);
- printf("t2 a= %d\n",aaa);
- sleep(1);
- }
- }
- int main()
- {
- pthread_t th1;
- pthread_t th2;
- pthread_create(&th1,NULL,thread_1,NULL);
- pthread_create(&th2,NULL,thread_2,NULL);
- while(1)
- {
- sleep(10);
- }
- }
复制代码
不加锁的情况如下
加互斥锁以后的运行结果如下
因为加锁以后,虽然频率相同,但线程1操作变量时线程2在等待线程1的解锁。因此相对能够看出变量是加1减1比较规律的,而不加锁的情况就不好说了。粗线的一个应用。出了是变量,互斥锁还可以对操作进行互斥。互斥锁还有阻塞式和非阻塞式的。多加思索和联系可以在做项目时能够对遇到的程序问题有比较好的解决思路,仅以此勉励自己。
目前的测试都在在MYD-T113开发板上进行的,作为一个Linux开发板,基础外设和必要的开发库都是具备的,无论是做工还是使用上也是比较方便的,这一点要给好评。在使用中发现无线网连接后,有时运行SCP命令会比较迟钝,如果此时再连接一次**,就恢复正常了,也许这是个小问题,也许是我使用的不太对,留着**查清楚。
|
|