PPP LWIP中斷安全 線程安全

 在做ppp驅動3G/4G模塊時,用的LWIP協議棧,循環接收處理串口數據時,會調用這2個函數中的一個
pppos_input();
pppos_input_tcpip()

看下面這段話,我理解的意思是,pppos_input_tcpip()是線程安全的,可以隨便調用, 但是也不要從串口收到一個字節就調用1 次, 而pppos_input()是線程不安全的,如果在運行pppos_input()的時候,不能調用NEVER call pppos_connect(), pppos_listen() and ppp_free() ,這些函數。


PPPoS input path (raw API, IRQ safe API, TCPIP API)
=====================================================

Received data on serial port should be sent to lwIP using the pppos_input()
function or the pppos_input_tcpip() function.

If NO_SYS is 1 and if PPP_INPROC_IRQ_SAFE is 0 (the default), pppos_input()
is not IRQ safe and then *MUST* only be called inside your main loop.

Whatever the NO_SYS value, if PPP_INPROC_IRQ_SAFE is 1, pppos_input() is IRQ
safe and can be safely called from an interrupt context, using that is going
to reduce your need of buffer if pppos_input() is called byte after byte in
your rx serial interrupt.

if NO_SYS is 0, the thread safe way outside an interrupt context is to use
the pppos_input_tcpip() function to pass input data to the lwIP core thread
using the TCPIP API. This is thread safe in all cases but you should avoid
passing data byte after byte because it uses heavy locking (mailbox) and it
allocates pbuf, better fill them !

if NO_SYS is 0 and if PPP_INPROC_IRQ_SAFE is 1, you may also use pppos_input()
from an RX thread, however pppos_input() is not thread safe by itself. You can
do that *BUT* you should NEVER call pppos_connect(), pppos_listen() and
ppp_free() if pppos_input() can still be running, doing this is NOT thread safe
at all. Using PPP_INPROC_IRQ_SAFE from an RX thread is discouraged unless you
really know what you are doing, your move ;-)


下面只分析pppos_input_tcpip,因爲這個簡單,
err_t
pppos_input_tcpip(ppp_pcb *ppp, u8_t *s, int l)
{
  struct pbuf *p;
  err_t err;

  p = pbuf_alloc(PBUF_RAW, l, PBUF_POOL);
  if (!p) {
    return ERR_MEM;
  }
  pbuf_take(p, s, l);

  err = tcpip_inpkt(p, ppp_netif(ppp), pppos_input_sys);
  if (err != ERR_OK) {
     pbuf_free(p);
  }
  return err;
}

上面可以看出來,它是怎麼實現線程安全的,當pppos_input_tcpip收到數據時,它直接分配1個pbuf,把數據放在pbuf中,然後提交處理,這種辦法的缺點也是很明顯的,數據每次收到的串口數據較少時,會頻率的分配內存釋放內存,嚴重浪費了CPU資源, 它是以佔用內存,佔用CPU資源爲代價來實現線程安全的。

pppos_input就不分析了,大概就是直接分析pppos串口數據,剔除escaped轉義字符,直接給上層(TCPIP)提交ether報文,我認爲這樣處理效率高多了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章