LWIP之API_MSG結構及其實現

 

009-5-11 LWIP之API_MSG結構及其實現
 
       從上面一篇的socket實現來看,如果要評起到最關鍵作用的一個結構體,那麼struct api_msg當之無愧。先看下它的定義:
/** This struct contains a function to execute in another thread context and
    a struct api_msg_msg that serves as an argument for this function.
    This is passed to tcpip_apimsg to execute functions in tcpip_thread context. */
struct api_msg
{
  /** function to execute in tcpip_thread context */
  void (* function)(struct api_msg_msg *msg);
  /** arguments for this function */
  struct api_msg_msg msg;
};
功能說的很清楚。但是具體怎麼個操作法還是不知道,沒關係,接着看它的調用。
 
       舉一個例子,剛好是上一篇中調用,但是沒有看具體實現的
err_t netconn_getaddr(struct netconn *conn, struct ip_addr *addr, u16_t *port, u8_t local)
{
  struct api_msg msg;
 
  msg.function = do_getaddr;
  msg.msg.conn = conn;
  msg.msg.msg.ad.ipaddr = addr;
  msg.msg.msg.ad.port = port;
  msg.msg.msg.ad.local = local;
  TCPIP_APIMSG(&msg);
 
  return conn->err;
}
說明一下,api_msg結構幾乎都是在netconn_xxx函數中被調用,方式千篇一律,除了msg.funcion的賦值不一樣外。上面的調用很簡單,對該結構體變量賦值,接着就是調用TCPIP_APIMSG,這個函數上面講過,可過去看下。既然如此,就不得不說mbox及其相關函數了。
static sys_mbox_t mbox = SYS_MBOX_NULL;【tcp.c】
再看sys_mbox_t的定義,在【src\include\lwip\sys.h】中
/* For a totally minimal and standalone system, we provide null
   definitions of the sys_ functions. */
typedef u8_t sys_sem_t;
typedef u8_t sys_mbox_t;
typedef u8_t sys_prot_t;
可以看到這裏只是簡單的定義成了u8類型,注意上面的紅色字體的說明,很明顯這個是可移植的一部分,需要根據不同的平臺,不同的操作系統具體定義。可以借鑑焦海波大俠的關於ucos上對lwip的移植筆記來看。
       我們可以看到在api_msg結構的處理過程中,所有的信息都是包含在api_msg_msg結構體中的,api_msg只是將其和function簡單的組合了。下面看下這個牛結構的定義:
/** This struct includes everything that is necessary to execute a function
    for a netconn in another thread context (mainly used to process netconns
    in the tcpip_thread context to be thread safe). */
struct api_msg_msg
{
  /** The netconn which to process - always needed: it includes the semaphore
      which is used to block the application thread until the function finished. */
  struct netconn *conn;
  /** Depending on the executed function, one of these union members is used */
  union
{
    /** used for do_send */
    struct netbuf *b;
    /** used for do_newconn */
    struct {
      u8_t proto;
    } n;
    /** used for do_bind and do_connect */
    struct {
      struct ip_addr *ipaddr;
      u16_t port;
    } bc;
    /** used for do_getaddr */
    struct {
      struct ip_addr *ipaddr;
      u16_t *port;
      u8_t local;
    } ad;
    /** used for do_write */
    struct {
      const void *dataptr;
      int len;
      u8_t apiflags;
    } w;
    /** used ofr do_recv */
    struct {
      u16_t len;
    } r;
#if LWIP_IGMP
    /** used for do_join_leave_group */
    struct {
      struct ip_addr *multiaddr;
      struct ip_addr *interface;
      enum netconn_igmp join_or_leave;
    } jl;
#endif /* LWIP_IGMP */
#if TCP_LISTEN_BACKLOG
    struct {
      u8_t backlog;
    } lb;
#endif /* TCP_LISTEN_BACKLOG */
  } msg;
};

一個很合理的設計,至少筆者是這麼認爲的。關鍵在於msg union的設計。

本文出自 “bluefish” 博客,請務必保留此出處http://bluefish.blog.51cto.com/214870/158414
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章