1. 程式人生 > >PX4編譯過程解讀程式碼1

PX4編譯過程解讀程式碼1

第一個編譯檔案DriverFramework.cpp

位置:src/lib/DriverFraamework/framework/src/DriverFramework.cpp

#define SHOW_STATS 0
namespace DriverFramework   //名稱空間DriverFramework
{

型別

class HRTWorkQueue : public DisableCopy //HRTWorkQueue公有繼承DisableCopy
{
public:
    static HRTWorkQueue &instance();

    int initialize();   //初始化
    void finalize();

    void scheduleWorkItem(WorkHandle &wh);

    void shutdown();
    void enableStats(bool enable);

    static void *process_trampoline(void * /*arg*/);

private:
    HRTWorkQueue() = default;
    ~HRTWorkQueue() = default;

    void process();

    bool    m_enable_stats = false;

    SyncObj m_reschedule;
};
};

using namespace DriverFramework;

Global Variables 全域性變數

namespace DriverFramework
{
RunStatus *g_run_status = nullptr;  //定義*g_run_status為空指標,不會發生二義性
};

靜態變數

static pthread_t g_tid; 
static SyncObj *g_framework;    //QuRT C++ compiler不支援靜態類的初始化

靜態函式

static uint64_t TsToAbstime(struct timespec *ts)    //TsToAbstime表示得到系統實時時鐘的絕對時間,timespec就是實時時間;若獲得絕對時間成功,return 0,否則返回非零
{
    uint64_t result = (uint64_t)(ts->tv_sec) * 1000000UL;
    result += ts->tv_nsec / 1000;
    return result;
}
static uint64_t starttime = 0;  //靜態常量開始時間為零
static void initStartTime() //靜態初始化開始時間函式
{
    struct timespec ts = {};    //實際時間為空陣列
    int ret = absoluteTime(ts); //將絕對時間值賦值給ret
    if (ret != 0) { 如果ret不為零,列印“錯誤:絕對時間返回為ret”
        printf("ERROR: absoluteTime returned (%d)\n", ret);
        return;
    }

    starttime = TsToAbstime(&ts);   //將獲得的絕對時間賦值給starttime
}

static inline uint64_t getStartTime()   //行內函數,呼叫時會檢查函式傳參是否正確,也不需要預編譯,獲得starttime
{
    return starttime;
}

全域性函式

//不要在這裡使用DF_LOG_XXX,因為它會導致遞迴迴圈
uint64_t DriverFramework::offsetTime()  //實現偏移量時間offsetTime函式
{
    struct timespec ts = {};    //實際時間陣列為空
    int ret = absoluteTime(ts); //將得到的絕對時間賦值給整形ret
    if (ret != 0) {
        printf("ERROR: absoluteTime returned (%d)", ret);
        return 0;
    }
    // 時間單位是微秒
    uint64_t result = TsToAbstime(&ts) - getStartTime();    //得到的結果=絕對時間-開始得到的時間
    return result;
}
timespec DriverFramework::offsetTimeToAbsoluteTime(uint64_t offset_time)    //實現絕對時間偏移量函式
{
    struct timespec ts = {};
    uint64_t abs_time = offset_time + getStartTime();   //絕對時間=時間偏移量+得到開始時間
    ts.tv_sec = abs_time / 1000000; //ts時間的秒計數的值
    ts.tv_nsec = (abs_time % 1000000) * 1000;   //ts時間的納秒計數的值
    return ts;
}
#if DF_ENABLE_BACKTRACE
void DriverFramework::backtrace()   //backtrace()函式用來獲取程式中當前函式的回溯資訊
{
    void *buffer[10];   //backtrace()函式的返回值為buffer中的條目數量
    char **callstack;
    int bt_size;    //引數size指定了buffer中可存放的返回地址的數量
    int idx;
    bt_size = ::backtrace(buffer, 10);
    callstack = ::backtrace_symbols(buffer, bt_size);   //backtrace_symbols()函式可以將每一個返回值都翻譯成“函式名+函式內偏移量+函式返回值”
    DF_LOG_INFO("Backtrace: %d", bt_size);
    for (idx = 0; idx < bt_size; idx++) {
        DF_LOG_INFO("%s", callstack[idx]);
    }
    free(callstack);    //經過翻譯後的函式回溯資訊放到backtrace_symbols()的返回值中,如果失敗則返回NULL。需要注意,返回值本身是在backtrace_symbols()函式內部進行malloc的,所以必須在後續顯式地free掉。
}
#endif

類實現方式

//RunStatus執行狀態
bool RunStatus::check()
{
    m_lock.lock();
    bool ret = m_run;
    m_lock.unlock();
    return ret;
}
void RunStatus::terminate()
{
    m_lock.lock();
    m_run = false;
    m_lock.unlock();
}
//框架
void Framework::shutdown()
{
    // 釋放HRTWorkQueue資源
    HRTWorkQueue::instance().finalize();

    // 釋放WorkMgr資源
    WorkMgr::finalize();

    // 釋放DevMgr資源
    DevMgr::finalize();

    // 允許框架退出
    g_framework->lock();
    g_framework->signal();
    g_framework->unlock();
}

int Framework::initialize()
{
    initStartTime(); // 必須在呼叫任何其他計時方法之前初始化

    DF_LOG_DEBUG("Framework::initialize");

    g_framework = new SyncObj;

    if (!g_framework) {
        DF_LOG_ERR("ERROR: falled to allocate g_framework");
        return -1;
    }

    g_run_status = new RunStatus;

    if (!g_run_status) {
        DF_LOG_ERR("g_run_status allocation failed");
        return -2;
    }

    struct timespec ts = {};

    int ret = absoluteTime(ts);

    if (ret != 0) {
        DF_LOG_ERR("ERROR: absoluteTime returned (%d)", ret);
        return -4;
    }

    ret = HRTWorkQueue::instance().initialize();

    if (ret < 0) {
        return ret - 10;
    }

    DF_LOG_DEBUG("Calling DevMgr::initialize");
    ret = DevMgr::initialize();

    if (ret < 0) {
        return ret - 20;
    }

    DF_LOG_DEBUG("Calling WorkMgr::initialize");
    ret = WorkMgr::initialize();

    if (ret < 0) {
        return ret - 30;
    }

    return 0;
}

void Framework::waitForShutdown()
{
    // 阻止直到請求關閉
    g_framework->lock();
    g_framework->waitOnSignal(0);
    g_framework->unlock();

    delete g_framework;
    g_framework = nullptr;
}
#ifndef __DF_QURT
// pthread_setschedparam似乎不適用於QURT,在DSP上面的RTOS是QuRT。
static void show_sched_settings()
{
    int policy;
    struct sched_param param {};

    int ret = pthread_getschedparam(pthread_self(), &policy, &param);   //得到執行緒的許可權,pthread_self()是獲得的執行緒ID。policy執行緒的排程, SCHED_FIFO(先入先出),SCHED_RR(迴圈),SCHED_OTHER(實現定義的方法)。

    if (ret != 0) {
        DF_LOG_ERR("pthread_getschedparam failed (%d)", ret);
    }

    DF_LOG_DEBUG("pthread info: policy=%s priority=%d",
             (policy == SCHED_OTHER) ? "SCHED_OTHER" :
             (policy == SCHED_FIFO)  ? "SCHED_FIFO" :
             (policy == SCHED_RR)    ? "SCHED_RR" :
             "UNKNOWN",
             param.sched_priority);
}

static int setRealtimeSched()   //設定實時排程
{
    int policy = SCHED_FIFO;    //排程策略採用先進先出
    sched_param param {};

    param.sched_priority = 10;  //優先順序設定為10

    int ret = pthread_setschedparam(pthread_self(), policy, &param);    //設定執行緒的許可權

    show_sched_settings();

    return ret;
}
#endif

void *HRTWorkQueue::process_trampoline(void *arg)
{
    DF_LOG_DEBUG("HRTWorkQueue::process_trampoline");

#ifndef __DF_QURT
    int ret = setRealtimeSched();

    if (ret != 0) {
        DF_LOG_ERR("WARNING: setRealtimeSched failed (not run as root?)");
    }

#endif

#ifdef __DF_LINUX
    prctl(PR_SET_NAME, "DFWorker"); //設定執行緒名稱為DFWorker
#endif

    DF_LOG_DEBUG("process_trampoline %d", ret);

    instance().process();

    return nullptr;
}

HRTWorkQueue &HRTWorkQueue::instance()
{
    static HRTWorkQueue *instance = nullptr;

    if (!instance) {
        instance = new HRTWorkQueue();
    }

    return *instance;
}

int HRTWorkQueue::initialize()
{
    DF_LOG_DEBUG("HRTWorkQueue::initialize");

    pthread_attr_t attr {};
    int ret = pthread_attr_init(&attr);

    if (ret != 0) {
        DF_LOG_ERR("pthread_attr_init failed");
        return -1;
    }

#ifdef __DF_QURT
    // 嘗試設定堆疊大小。 此堆疊大小稍後在感測器驅動程式中的_measure()呼叫中使用,至少在QURT上使用。
    const size_t stacksize = 3072;

    if (pthread_attr_setstacksize(&attr, stacksize) != 0) {
        DF_LOG_ERR("failed to set stack size of %lu bytes", stacksize);
        return -2;
    }

#endif

    // 建立高優先順序工作執行緒
    if (pthread_create(&g_tid, &attr, process_trampoline, nullptr)) {
        return -3;
    }

    DF_LOG_DEBUG("pthread_create success");

        return 0;
}

void HRTWorkQueue::finalize()
{
    DF_LOG_DEBUG("HRTWorkQueue::finalize");

    shutdown();

    // 等待工作佇列執行緒退出
    pthread_join(g_tid, nullptr);
}

void HRTWorkQueue::scheduleWorkItem(WorkHandle &wh)
{
    DF_LOG_DEBUG("HRTWorkQueue::scheduleWorkItem (%p)", &wh);

    // 控制代碼已知有效
    int ret = WorkItems::schedule(wh.m_handle);

    DF_LOG_DEBUG("WorkItems::schedule %d", ret);

    if (ret == 0) {
        wh.m_errno = 0;
        m_reschedule.lock();
        m_reschedule.signal();
        m_reschedule.unlock();

    } else if (ret == EBADF) {
        wh.m_errno = EBADF;
        wh.m_handle = -1;

    } else {
        wh.m_errno = ret;
    }

}

void HRTWorkQueue::shutdown()
{
    DF_LOG_DEBUG("HRTWorkQueue::shutdown");

    if (g_run_status) {
        g_run_status->terminate();
}

    m_reschedule.lock();
    m_reschedule.signal();
    m_reschedule.unlock();
}

void HRTWorkQueue::process()
{
    DF_LOG_DEBUG("HRTWorkQueue::process");
    uint64_t next;
    uint64_t now;

    while (g_run_status && g_run_status->check()) {
        now = offsetTime();

        // 如果沒有預定,每10秒喚醒一次
        next = now + 10000000;

        WorkItems::processExpiredWorkItems(next);

        now = offsetTime();
        DF_LOG_DEBUG("now=%" PRIu64, now);
#ifdef __DF_QURT

        // 以適應平臺中程序睡眠的不準確性
            if (next > now + 200) {
#else

        if (next > now) {
#endif
            uint64_t wait_time_usec = next - now;

            DF_LOG_DEBUG("HRTWorkQueue::process waiting for work (%" PRIi64 "usec)", wait_time_usec);
            // 等待直到下個專案到期或者直到有新的專案被安排
            m_reschedule.lock();
            m_reschedule.waitOnSignal(wait_time_usec);
            m_reschedule.unlock();
            DF_LOG_DEBUG("HRTWorkQueue::process done wait");
            }

        DF_LOG_DEBUG("HRTWorkQueue::process not waiting for work");
    }
};

// 在這篇文章中才能訪問HRTWorkQueue::scheduleWorkItem
int WorkMgr::schedule(DriverFramework::WorkHandle &wh)
{
    DF_LOG_DEBUG("WorkMgr::schedule");
    HRTWorkQueue::instance().scheduleWorkItem(wh);
    return (wh.m_errno == 0) ? 0 : -1;
}