关于用一个函数创建多个任务的问题
Posted yanhc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于用一个函数创建多个任务的问题相关的知识,希望对你有一定的参考价值。
在LwIP的netif目录下lwip-2.1.2\src\netif有一个slipif.c的示例,即做了一个SLIP网络接口的模板,其中有一个地方是创建一个任务/线程接收数据。之前在开发板上做的时候,因为有2个以上串口,就想如果把slipif.c创建2次,每个串口用一个,那不是太傻了么。而且,slip.c就像一个驱动,普通电脑的驱动,win or linux,比如,如果有多个usb接口,不会写两份usb驱动吧。而这个接收任务中有一个输入参数是netif,那是不是可以两个串口通过netif区分呢。
1 #if SLIP_USE_RX_THREAD 2 /** 3 * The SLIP input thread. 4 * 5 * Feed the IP layer with incoming packets 6 * 7 * @param nf the lwip network interface structure for this slipif 8 */ 9 static void 10 slipif_loop_thread(void *nf) 11 { 12 u8_t c; 13 struct netif *netif = (struct netif *)nf; 14 struct slipif_priv *priv = (struct slipif_priv *)netif->state; 15 16 while (1) { 17 if (sio_read(priv->sd, &c, 1) > 0) { 18 slipif_rxbyte_input(netif, c); 19 } 20 } 21 } 22 #endif /* SLIP_USE_RX_THREAD */
后来,实际就是这样做的,在创建slip netif时,都用下面方式创建,
1 netif_add(&snetif3, &uartno, &slipif_init, &ip_input); 2 3 netif_add(&snetif5, &uartno, &slipif_init, &ip_input);
但在slipif_init里会根据传递进来的是哪个串口,分别创建对应的接收任务(其实还有二值信号量,这个因为是全局变量,所以,从一开始对不同任务就是独立的),并将netif作为函数参数传递进去。这样,后面接收任务就可以依据对应的netif操作。
1 err_t slipif_init(struct netif *netif) 2 { 3 ... 4 /* create binary semaphore used for informing usart reception */ 5 if (sem_slip[sio_num] == NULL) 6 { 7 vSemaphoreCreateBinary(sem_slip[sio_num]); 8 xSemaphoreTake( sem_slip[sio_num], 0); 9 } 10 11 #if SLIP_USE_RX_THREAD 12 /* Create a thread to poll the serial line. */ 13 sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop_thread, netif, 14 SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO); 15 #endif /* SLIP_USE_RX_THREAD */ 16 return ERR_OK; 17 }
虽然上面的操作实际可行,但一直没想明白原因。在学习了任务相关东西之后,才终于明白。
对于两个串口任务来说,其代码段只有一份,也就是都是接收任务。
对于变量部分,一是netif和二值信号量两个全局变量,二是内部使用的临时变量。前者是全局区分的,二者则在两个任务堆栈上,因此,都是独立的。
假定两个任务为A、B,在执行A任务时,会使用A任务的PC指针,该PC指针指向A任务上次执行的位置,对于变量部分,全局变量是独立的,局部变量是在A任务堆栈上的。
在执行B任务时,则会使用B任务的PC指针,由于代码段是只读的,所以,两个任务都执行同一片代码段,没有任何关系。而对于可写的变量部分,又都是独立的,因此,也没有任何关系。
综上,一个驱动实现,可以创建多个任务,对于全局变量需要区分开,对于局部变量通过任务堆栈区分开了。
以上是关于关于用一个函数创建多个任务的问题的主要内容,如果未能解决你的问题,请参考以下文章