eventloop(ril.cpp)函數中定義的管道的作用(Android)

在(android源碼目錄)/hardware/ril/libril/ril.cpp文件中定義了一個管道:

/*此段代碼在ril.cpp中*/
static void *eventLoop(void *param)
{
    ret = pipe(filedes);
    …其他代碼…
    s_fdWakeupRead = filedes[0];
    s_fdWakeupWrite = filedes[1];
    /*將讀管道設爲非阻塞方式*/
    fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK);
    /*設置s_wakeupfd_event事件的處理函數爲processWakeupCallback*/
    ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,
                processWakeupCallback, NULL);/*processWakeupCallback函數的作用是清空管道*/
    /*調用rilEventAddWakeup函數,該函數內容下文已附*/
    rilEventAddWakeup (&s_wakeupfd_event);
    // Only returns on error
ril_event_loop();
…其他代碼…
}

static void rilEventAddWakeup(struct ril_event *ev)/*此段代碼在ril.cpp中*/
{
    ril_event_add(ev);/*把ev添加到監視列表watch_table數組,並將ev->fd加入readFds描述符集*/
    triggerEvLoop();/*如果此時不在evenloop線程中了,就把evenloop喚醒,該函數內容下文已附*/
}

static void triggerEvLoop()/*此段代碼在ril.cpp中*/
{
    int ret;
    if (!pthread_equal(pthread_self(), s_tid_dispatch)) {
        /* trigger event loop to wakeup. No reason to do this,
         * if we're in the event loop thread */
         do {
            ret = write (s_fdWakeupWrite, " ", 1);
         } while (ret < 0 && errno == EINTR);
    }
}

可以從ril_event_add和triggerEvLoop函數看出,每次調用rilEventAddWakeup時,就把安裝了processWakeupCallback(作用是清空管道)處理函數的s_wakeupfd_event事件寫入監視列表watch_table[]數組,然後再向管道內寫入一個字節的空格。

管道的作用是這樣的,eventloop函數所在的進程向下調用ril_event_loop()函數(ril_event.cpp),後者將readFds做了一個本地備份(自然s_wakeupfd_event的描述符也在裏面,因爲ril_event_add已將將ev->fd加入readFds描述符集)。然後再向下遇到了一個select

n = select(nfds, &rfds, NULL, NULL, ptv);

此時如果管道里面有數據,s_fdWakeupRead即爲可用,則select不會阻塞。因此,如果eventloop進程在這裏因爲沒有可用的讀描述符而被阻塞的話,執行rilEventAddWakeup後,管道內被寫入了至少一個空格,則rfds中至少將有一個描述符變得可用,select函數返回。因此eventloop線程(此時該進程正在執行ril_event_loop函數)被select的阻塞的情況(如果被阻塞的話)將被解除。

eventloop線程繼續向下執行,被寫入監視列表watch_table數組的s_wakeupfd_event事件在ril_event_loop函數(ril_event.cpp)調用函數processReadReadies(&rfds, n)時放入了pending_list中,並隨着firePending()函數的執行,processWakeupCallback函數(作用是清空管道)也得到執行。這樣,管道的讀描述符重新變得不可用,使其不影響正常的select功能。相當於將喚醒eventloop進程的“扳機”重新歸位,等待下一次某個進程需要時再次調用的triggerEvLoop。

總的來說,就是通過管道內的數據有無,控制select是否解除阻塞的過程。

轉載:http://hi.baidu.com/mcu99/blog/item/1b408b2c530282e48b13991e.html

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