关于用一个函数创建多个任务的问题

在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指针,由于代码段是只读的,所以,两个任务都执行同一片代码段,没有任何关系。而对于可写的变量部分,又都是独立的,因此,也没有任何关系。

综上,一个驱动实现,可以创建多个任务,对于全局变量需要区分开,对于局部变量通过任务堆栈区分开了。

猜你喜欢

转载自www.cnblogs.com/yanhc/p/12677555.html