NuttX的學習筆記 8

好了,新開一篇繼續新的內容

Task Scheduling Interfaces

任務調度接口

By default, NuttX performs strict priority scheduling: Tasks of higher priority have exclusive access to the CPU until they become blocked. At that time, the CPU is available to tasks of lower priority. Tasks of equal priority are scheduled FIFO.

默認情況下,NuttX執行嚴格的優先級調度:更高優先級的任務獨佔訪問CPU,直到他們變得阻塞。當時,可用CPU低優先級的任務。相同優先級的任務計劃FIFO。

Optionally, a Nuttx task or thread can be configured with round-robin or sporadic scheduler. The round-roben is similar to priority scheduling except that tasks with equal priority and share CPU time via time-slicing. The time-slice interval is a constant determined by the configuration setting CONFIG_RR_INTERVAL to a positive, non-zero value. Sporadic scheduling scheduling is more complex, varying the priority of a thread over a replenishment period. Support for sporadic scheduling is enabled by the configuration option CONFIG_SCHED_SPORADIC.

可選的Nuttx任務或線程可以配置循環或零星的調度器。round-roben類似於優先級調度,除了任務同等優先級和通過次共享CPU時間。分配間隔設置的配置是一個常數由CONFIG_RR_INTERVAL積極,非零值。零星的調度調度更加複雜,不同的優先級線程補充一段。支持配置選項CONFIG_SCHED_SPORADIC啓用了零星的調度。

首先,在-> RTOS Features -> Tasks and Scheduling中啓用 Support sporadic scheduling 而參數CONFIG_RR_INTERVAL 只要調整Round robin timeslice (MSEC) 即可。

sched_setparam

int sched_setparam(pid_t pid, const struct sched_param *param);

這個函數使用pid設置指定任務的調度優先級。

sched_getparam

int sched_getparam (pid_t pid, struct sched_param *param);

這個函數使用pid獲取指定任務的調度優先級。

sched_setscheduler

int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param);

sched_setscheduler()通過pid確定任務並設置調度策略和任務的優先級。如果pid等於零,調用線程的調度程序將參數參數。持有新策略下的線程的優先級。

sched_getscheduler

int sched_getscheduler (pid_t pid);

sched_setscheduler()通過pid確定任務並獲取調度策略。

sched_yield

int sched_yield(void);

調用這個函數將使任務讓出CPU。

sched_get_priority_max

int sched_get_priority_max (int policy);
調用這個函數將返回 指定的使特殊調度策略 的最高可能的任務優先級。

sched_get_priority_min

int sched_get_priority_min (int policy);
與上面的相反,上面的是獲取最大,這個是獲取最小。

sched_get_rr_interval

int sched_get_rr_interval (pid_t pid, struct timespec *interval);
sched_rr_get_interval()將獲取確定pid任務的時間片間隔並寫入由 interval 指針傳入的時間片結構體中。

任務調度的接口實驗

前兩個函數接口可以一起調試,將已創建任務的任務優先級往下調。並查詢其值。這裏先要說一下這個測試代碼:

#include <nuttx/config.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#define CONFIG_EXAMPLES_HELLO_TASK_PRIORITY  SCHED_PRIORITY_DEFAULT
#define CONFIG_EXAMPLES_HELLO_TASK_STACKSIZE 2048

int print_hello(int argc, char *argv[]) {

    long int i;
    printf("%s: pid = %d \n", argv[0], getpid());
    for (i = 0; i < 20; ++i) {
        printf("%d\n", i);
    }
    exit(EXIT_SUCCESS);
}

int hello_task_main(int argc, char *argv[]) {
    int ret;

    /* Started print_hello */
    pid_t print_hello_pid;
    print_hello_pid = task_create("print_hello",
    CONFIG_EXAMPLES_HELLO_TASK_PRIORITY,
    CONFIG_EXAMPLES_HELLO_TASK_STACKSIZE, print_hello, &argv[1]);
    if (print_hello_pid < 0) {
        int errcode = errno;
        printf("%s: ERROR: Failed to start print_hello: %d\n", argv[0],
                errcode);
        return EXIT_FAILURE;
    } else
        printf("%s: Started print_hello at PID=%d\n", argv[0], print_hello_pid);

    /* print print_hello sched_param  */
    struct sched_param print_hello_sched_param;
    ret = sched_getparam(print_hello_pid, &print_hello_sched_param);
    if (ret == 0) {
        printf("%s: Get print_hello priority success\n", argv[0]);
        printf("print_hello_sched_param:\n  sched_priority: %d\n",
                print_hello_sched_param.sched_priority);
        printf("  sched_ss_low_priority: %d\n",
                print_hello_sched_param.sched_ss_low_priority);
        printf("  sched_ss_repl_period:\n    tv_sec: %d\n",
                print_hello_sched_param.sched_ss_repl_period.tv_sec);
        printf("    tv_nsec: %d\n",
                print_hello_sched_param.sched_ss_repl_period.tv_nsec);
        printf("  sched_ss_init_budget:\n    tv_sec: %d\n",
                print_hello_sched_param.sched_ss_init_budget.tv_sec);
        printf("    tv_nsec: %d\n  sched_ss_max_repl: %d\n",
                print_hello_sched_param.sched_ss_init_budget.tv_nsec,
                print_hello_sched_param.sched_ss_max_repl);
    } else {
        printf("%s: ERROR: Failed to get print_hello priority\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    /* Set print_hello priority to 50  */
    print_hello_sched_param.sched_priority = 50;
    ret = sched_setparam(print_hello_pid, &print_hello_sched_param);
    if (ret == 0) {
        printf("%s: Set print_hello priority to 50\n", argv[0]);

    } else {
        printf("%s: ERROR: Failed to set print_hello priority to 50\n",
                argv[0]);
        int errcode = errno;
        switch (errcode) {
        case EINVAL:
            printf("sched_setparam: %s\n", EINVAL_STR);
            break;
        case EPERM:
            printf("sched_setparam: %s\n", EPERM_STR);
            break;
        case ESRCH:
            printf("sched_setparam: %s\n", ESRCH_STR);
            break;
        default:
            break;
        }
        exit(EXIT_FAILURE);
    }

    /* print print_hello sched_param  */
    ret = sched_getparam(print_hello_pid, &print_hello_sched_param);
    if (ret == 0) {
        printf("%s: Get print_hello priority success\n", argv[0]);
        printf("print_hello_sched_param:\n  sched_priority: %d\n",
                print_hello_sched_param.sched_priority);
        printf("  sched_ss_low_priority: %d\n",
                print_hello_sched_param.sched_ss_low_priority);
        printf("  sched_ss_repl_period:\n    tv_sec: %d\n",
                print_hello_sched_param.sched_ss_repl_period.tv_sec);
        printf("    tv_nsec: %d\n",
                print_hello_sched_param.sched_ss_repl_period.tv_nsec);
        printf("  sched_ss_init_budget:\n    tv_sec: %d\n",
                print_hello_sched_param.sched_ss_init_budget.tv_sec);
        printf("    tv_nsec: %d\n  sched_ss_max_repl: %d\n",
                print_hello_sched_param.sched_ss_init_budget.tv_nsec,
                print_hello_sched_param.sched_ss_max_repl);
    } else {
        printf("%s: ERROR: Failed to get print_hello priority\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
    return EXIT_SUCCESS;
}

因爲裏面還摻着 print_hello 的輸出,將其去掉,運行結果,:

nsh> hello_task
hello_task: Started print_hello at PID=3
hello_task: Get print_hello priority success
print_hello_sched_param:
  sched_priority: 100
  sched_ss_low_priority: 0
  sched_ss_repl_period:
    tv_sec: 0
    tv_nsec: 0
  sched_ss_init_budget:
    tv_sec: 0
    tv_nsec: 0
print_hello: pid = 3 
  sched_ss_max_repl: 0
hello_task: Set print_hello priority to 50
hello_task: Get print_hello priority success
print_hello_sched_param:
  sched_priority: 50
  sched_ss_low_priority: 0
  sched_ss_repl_period:
    tv_sec: 0
    tv_nsec: 0
  sched_ss_init_budget:
    tv_sec: 0
    tv_nsec: 0
  sched_ss_max_repl: 0
nsh> 

雖然時間片的其他都是0而且我也不知倒是幹嘛的,但是至少可以修改任務的優先級(priority)。好,繼續。

下兩個是 sched_setschedulersched_getscheduler 。按照慣例,先獲取,再更改,再獲取。
獲取一次後,發現

hello_task: Get myself policy success
hello_task: myself policy = 2
hello_task: Get print_hello policy success
hello_task: print_hello policy = 1

這裏我就有點奇怪了,爲什麼先啓動的 hello_task 調度策略爲2,後啓動的調度策略爲1。測試了很多遍,都是這樣。着實奇怪。然後又加了一個任務啓動,獲得其調度策略還是1:

hello_task: Get myself policy success
hello_task: myself policy = 2
hello_task: Started print_hello at PID=3
hello_task: Get print_hello policy success
hello_task: print_hello policy = 1
hello_task: Started print_world at PID=4
hello_task: Get print_world policy success
hello_task: print_world policy = 1

好吧,先放着。至少現在可以獲取。並且後面兩個進程的輸出幾乎是同時的。

print_hello: pid = 3
print_world: pid = 4
nsh> print_hello: Hello 0
print_world: World 0
print_hello: Hello 1
print_world: World 1
print_hello: Hello 2
print_world: World 2
print_hello: Hello 3
print_world: World 3
print_hello: Hello 4
print_world: World 4

將輸出的次數增加到100次,

print_world: World 96
print_hello: Hello 97
print_world: World 97
print_hello: Hello 98
print_world: World 98
print_hello: Hello 99
print_world: World 99

並沒有因爲改動了任務的調度策略而發生變化。
代碼如下:

#include <nuttx/config.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#define CONFIG_EXAMPLES_HELLO_TASK_PRIORITY  SCHED_PRIORITY_DEFAULT
#define CONFIG_EXAMPLES_HELLO_TASK_STACKSIZE 2048

int str2num(const char *s) {
    int rt = 0;
    while (*s >= '0' && *s <= '9') {
        rt = rt * 10 + (*s - '0');
        s++;
    }
    return rt;
}

int print_hello(int argc, char *argv[]) {

    int i;
    printf("%s: pid = %d \n", argv[0], getpid());
    int a = str2num(argv[1]);
    for (i = 0; i < a; ++i) {
        printf("%s: Hello %d\n", argv[0], i);
    }
    exit(EXIT_SUCCESS);
}

int print_world(int argc, char *argv[]) {

    int i;
    printf("%s: pid = %d \n", argv[0], getpid());
    int a = str2num(argv[1]);
    for (i = 0; i < a; ++i) {
        printf("%s: World %d\n", argv[0], i);
    }
    exit(EXIT_SUCCESS);
}

int hello_task_main(int argc, char *argv[]) {
    int ret;
    int print_hello_policy, hello_task_policy, print_world_policy;
    struct sched_param print_hello_sched_param;
    pid_t print_hello_pid, hello_task_pid, print_world_pid;

    /* print hello_task policy  */
    hello_task_pid = getpid();
    hello_task_policy = sched_getscheduler(hello_task_pid);
    if (hello_task_policy >= 0) {
        printf("%s: Get myself policy success\n", argv[0]);
        printf("%s: myself policy = %d\n", argv[0], hello_task_policy);
    } else {
        int errcode = errno;
        switch (errcode) {
        case ESRCH:
            printf("%s: ERROR: Failed to get myself policy: %s\n", argv[0],
            ESRCH_STR);
            break;
        default:
            printf("%s: ERROR: Failed to get myself policy\n", argv[0]);
            break;
        }
        exit(EXIT_FAILURE);
    }

    /* Started print_hello */
    print_hello_pid = task_create("print_hello",
    CONFIG_EXAMPLES_HELLO_TASK_PRIORITY,
    CONFIG_EXAMPLES_HELLO_TASK_STACKSIZE, print_hello, &argv[1]);
    if (print_hello_pid < 0) {
        int errcode = errno;
        printf("%s: ERROR: Failed to start print_hello: %d\n", argv[0],
                errcode);
        return EXIT_FAILURE;
    } else
        printf("%s: Started print_hello at PID=%d\n", argv[0], print_hello_pid);

    /* print print_hello policy  */
    print_hello_policy = sched_getscheduler(print_hello_pid);
    if (print_hello_policy >= 0) {
        printf("%s: Get print_hello policy success\n", argv[0]);
        printf("%s: print_hello policy = %d\n", argv[0], print_hello_policy);
    } else {
        int errcode = errno;
        switch (errcode) {
        case ESRCH:
            printf("%s: ERROR: Failed to get print_hello policy: %s\n", argv[0],
            ESRCH_STR);
            break;
        default:
            printf("%s: ERROR: Failed to get print_hello policy\n", argv[0]);
            break;
        }
        exit(EXIT_FAILURE);
    }

    /* Get print_hello sched_param */
    ret = sched_getparam(print_hello_pid, &print_hello_sched_param);
    if (ret == 0) {
        printf("%s: Get print_hello sched_param success\n", argv[0]);
    } else {
        printf("%s: ERROR: Failed to get print_hello sched_param\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    /* Change print_hello policy to SCHED_RR */
    ret = sched_setscheduler(print_hello_pid, SCHED_RR,
            &print_hello_sched_param);
    if (ret == OK) {
        printf("%s: Change print_hello policy to 2 success\n", argv[0]);
    } else {
        printf("%s: ERROR: Failed to change print_hello policy to 2\n",
                argv[0]);
        int errcode = errno;
        switch (errcode) {
        case EINVAL:
            printf("sched_setscheduler: %s\n", EINVAL_STR);
            break;
        case ESRCH:
            printf("sched_setscheduler: %s\n", ESRCH_STR);
            break;
        default:
            printf("sched_setscheduler: unknow reason!\n");
            break;
        }
        exit(EXIT_FAILURE);
    }

    /* Started print_world */
    print_world_pid = task_create("print_world",
    CONFIG_EXAMPLES_HELLO_TASK_PRIORITY,
    CONFIG_EXAMPLES_HELLO_TASK_STACKSIZE, print_world, &argv[1]);
    if (print_world_pid < 0) {
        int errcode = errno;
        printf("%s: ERROR: Failed to start print_world: %d\n", argv[0],
                errcode);
        exit(EXIT_FAILURE);
    } else
        printf("%s: Started print_world at PID=%d\n", argv[0], print_world_pid);

    /* print print_world policy  */
    print_world_policy = sched_getscheduler(print_world_pid);
    if (print_world_policy >= 0) {
        printf("%s: Get print_world policy success\n", argv[0]);
        printf("%s: print_world policy = %d\n", argv[0], print_world_policy);
    } else {
        int errcode = errno;
        switch (errcode) {
        case ESRCH:
            printf("%s: ERROR: Failed to get print_world policy: %s\n", argv[0],
            ESRCH_STR);
            break;
        default:
            printf("%s: ERROR: Failed to get print_world policy\n", argv[0]);
            break;
        }
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
    return EXIT_SUCCESS;
}

測試結果:

nsh> hello_task 20
hello_task: Get myself policy success
hello_task: myself policy = 2
hello_task: Started print_hello at PID=6
hello_task: Get print_hello policy success
hello_task: print_hello policy = 1
hello_task: Get print_hello sched_param success
hello_task: Change print_hello policy to 2 success
print_hello: pid = 6
hello_task: Started print_world at PID=7
print_world: pid = 7
print_hello: Hello 0
hello_task: Get print_world policy success
print_world: World 0
print_hello: Hello 1
hello_task: print_world policy = 1
print_world: World 1
print_hello: Hello 2
nsh> print_world: World 2
print_hello: Hello 3
print_world: World 3
print_hello: Hello 4
print_world: World 4
print_hello: Hello 5
print_world: World 5
print_hello: Hello 6
print_world: World 6
print_hello: Hello 7
print_world: World 7
print_hello: Hello 8
print_world: World 8
print_hello: Hello 9
print_world: World 9
print_hello: Hello 10
print_world: World 10
print_hello: Hello 11
print_world: World 11
print_hello: Hello 12
print_world: World 12
print_hello: Hello 13
print_world: World 13
print_hello: Hello 14
print_world: World 14
print_hello: Hello 15
print_world: World 15
print_hello: Hello 16
print_world: World 16
print_hello: Hello 17
print_world: World 17
print_hello: Hello 18
print_world: World 18
print_hello: Hello 19
print_world: World 19

閒暇至之餘,去查了一下任務調度策略。才發現並不是簡單的數字,而是有定義的。定義在

~/nuttx/nuttx/include/sched.h

#define SCHED_FIFO       1  /* FIFO priority scheduling policy */
#define SCHED_RR         2  /* Round robin scheduling policy */
#define SCHED_SPORADIC   3  /* Sporadic scheduling policy */
#define SCHED_OTHER      4  /* Not supported */

而關於這幾個定義,其中三個有其他說明:

SCHED_OTHER    分時調度策略
SCHED_FIFO     實時調度策略,先到先服務
SCHED_RR       實時調度策略,時間片輪轉

SHCED_RR和SCHED_FIFO的不同

SHCED_RR策略的進程的時間片用完時,系統將重新分配時間片,並置於就緒隊列尾。
SCHED_FIFO一旦佔用cpu則一直運行。一直運行直到有更高優先級任務到達或自己放棄。

我想這沒法解釋多個調度策略都爲1也就是 SCHED_FIFO 的任務爲何可以同時 printf 。(之後爲了區分1 2,在1 2的地方替換字符串)。甚至我在修改 print_helloprint_world 的任務優先級都爲不同值的時候也沒有出現預期的“一直運行”。關於這個問題,我這裏先放着。順便測試一下當任務爲死循環時會怎麼樣。
。。。
結果一樣,兩個 print_helloprint_world 出現了同時 printf 的情況。看樣子還真得先放着了。

繼續 sched_yield 那就讓print_hello 讓出CPU看看效果如何。

然而效果並不是那麼好,甚至說沒有效果。

print_hello: Hello 96
print_world: World 84
print_hello: Hello 97
print_world: World 85
print_hello: Hello 98
print_world: World 86
print_hello: Hello 99
print_world: World 87
print_world: World 88
print_world: World 89
print_world: World 90
print_world: World 91
print_world: World 92
print_world: World 93
print_world: World 94

一點都沒有要讓出來的意思。。。這讓我懷疑這是不是NuttX系統的調度系統沒有在 configure 打開。先放着,下一個。
sched_get_priority_max
在某種固定的調度策略下可取的優先級。

測試代碼:

#include <nuttx/config.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#define CONFIG_EXAMPLES_HELLO_TASK_PRIORITY  SCHED_PRIORITY_DEFAULT
#define CONFIG_EXAMPLES_HELLO_TASK_STACKSIZE 2048

int str2num(const char *s) {
    int rt = 0;
    while (*s >= '0' && *s <= '9') {
        rt = rt * 10 + (*s - '0');
        s++;
    }
    return rt;
}

int print_hello(int argc, char *argv[]) {

    int i;
    sleep(2);
    //printf("%s: pid = %d \n", argv[0], getpid());
    int a = str2num(argv[1]);
    for (i = 0; i < a; ++i) {
        sched_yield();
        printf("%s: Hello %d\n", argv[0], i);
    }
    exit(EXIT_SUCCESS);
}

int print_world(int argc, char *argv[]) {

    int i;
    sleep(2);
    //printf("%s: pid = %d \n", argv[0], getpid());
    int a = str2num(argv[1]);
    for (i = 0; i < a; ++i) {
        printf("%s: World %d\n", argv[0], i);
    }
    exit(EXIT_SUCCESS);
}

int hello_task_main(int argc, char *argv[]) {

    static char* scheduling_policies_str[4] = { "SCHED_FIFO", "SCHED_RR",
            "SCHED_SPORADIC", "SCHED_OTHER" };
    int ret;
    int print_hello_policy, hello_task_policy, print_world_policy;
    struct sched_param print_hello_sched_param;
    pid_t print_hello_pid, hello_task_pid, print_world_pid;

    /* print hello_task policy  */
    hello_task_pid = getpid();
    hello_task_policy = sched_getscheduler(hello_task_pid);
    if (hello_task_policy >= 0) {
        printf("%s: Get myself policy success\n", argv[0]);
        printf("%s: myself policy = %s\n", argv[0],
                scheduling_policies_str[hello_task_policy - 1]);
    } else {
        int errcode = errno;
        switch (errcode) {
        case ESRCH:
            printf("%s: ERROR: Failed to get myself policy: %s\n", argv[0],
            ESRCH_STR);
            break;
        default:
            printf("%s: ERROR: Failed to get myself policy\n", argv[0]);
            break;
        }
        exit(EXIT_FAILURE);
    }

    /* Started print_hello */
    print_hello_pid = task_create("print_hello",
    CONFIG_EXAMPLES_HELLO_TASK_PRIORITY - 1,
    CONFIG_EXAMPLES_HELLO_TASK_STACKSIZE, print_hello, &argv[1]);
    if (print_hello_pid < 0) {
        int errcode = errno;
        printf("%s: ERROR: Failed to start print_hello: %d\n", argv[0],
                errcode);
        return EXIT_FAILURE;
    } else
        printf("%s: Started print_hello at PID=%d\n", argv[0], print_hello_pid);

    /* print print_hello policy  */
    print_hello_policy = sched_getscheduler(print_hello_pid);
    if (print_hello_policy >= 0) {
        printf("%s: Get print_hello policy success\n", argv[0]);
        printf("%s: print_hello policy = %s\n", argv[0],
                scheduling_policies_str[print_hello_policy - 1]);
    } else {
        int errcode = errno;
        switch (errcode) {
        case ESRCH:
            printf("%s: ERROR: Failed to get print_hello policy: %s\n", argv[0],
            ESRCH_STR);
            break;
        default:
            printf("%s: ERROR: Failed to get print_hello policy\n", argv[0]);
            break;
        }
        exit(EXIT_FAILURE);
    }

    /* get the max priority in a policy */
    ret = sched_get_priority_max(SCHED_FIFO);
    if (ret == -1) {
        printf("%s: ERROR: Failed to get the max priority in %s\n", argv[0],
                "SCHED_FIFO");
    } else {
        printf("%s: get the max priority in %s success\n", argv[0],
                scheduling_policies_str[0]);
        auto int SCHED_FIFO_max_priority = ret;
        printf("%s: the max priority in %s is: %d\n", argv[0],
                scheduling_policies_str[0], SCHED_FIFO_max_priority);
    }

    exit(EXIT_SUCCESS);
    return EXIT_SUCCESS;
}

理論上說,應該可以獲取到255的。結果:

nsh> hello_task 5
hello_task: Get myself policy success
hello_task: myself policy = SCHED_RR
hello_task: Started print_hello at PID=3
hello_task: Get print_hello policy success
hello_task: print_hello policy = SCHED_FIFO
hello_task: get the max priority in SCHED_FIFO success
hello_task: the max priority in SCHED_FIFO is: 255
nsh> print_hello: Hello 0
print_hello: Hello 1
print_hello: Hello 2
print_hello: Hello 3
print_hello: Hello 4

和想象的一樣。下一個。
sched_get_priority_min
和上一個相反,理論上應該是1,代碼就把上面的max改成min即可
結果:

nsh> hello_task 5
hello_task: Get myself policy success
hello_task: myself policy = SCHED_RR
hello_task: Started print_hello at PID=3
hello_task: Get print_hello policy success
hello_task: print_hello policy = SCHED_FIFO
hello_task: get the min priority in SCHED_FIFO success
hello_task: the min priority in SCHED_FIFO is: 1
nsh> print_hello: Hello 0
print_hello: Hello 1
print_hello: Hello 2
print_hello: Hello 3
print_hello: Hello 4

正常。下一個是用來獲取時間片的函數,但是首先這個函數得運行在SCHED_RR 調度策略下。直接檢測hello_task 即可,因爲這個任務就是RR的。
代碼:

#include <sched.h>
#include <nuttx/config.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#define CONFIG_EXAMPLES_HELLO_TASK_PRIORITY  SCHED_PRIORITY_DEFAULT
#define CONFIG_EXAMPLES_HELLO_TASK_STACKSIZE 2048

int hello_task_main(int argc, char *argv[]) {

    static char* scheduling_policies_str[4] = { "SCHED_FIFO", "SCHED_RR",
            "SCHED_SPORADIC", "SCHED_OTHER" };
    int ret;
    int print_hello_policy, hello_task_policy, print_world_policy;
    struct sched_param print_hello_sched_param;
    struct timespec hello_task_timespec;
    pid_t print_hello_pid, hello_task_pid, print_world_pid;

    hello_task_pid = getpid();
    ret = sched_rr_get_interval(hello_task_pid, &hello_task_timespec);
    if (ret == 0) {
        printf("%s: Get myself timespec success\n", argv[0]);
        printf("%s:\nMy timespec:\n  tv_sec:  %d\n  tv_nsec: %d\n", argv[0], hello_task_timespec.tv_sec, hello_task_timespec.tv_nsec);
    } else {
        int errcode = errno;
        switch (errcode) {
        case EFAULT:
            printf("%s: ERROR: Failed to get myself timespec: %s\n", argv[0],
            EFAULT_STR);
            break;
        case EINVAL:
            printf("%s: ERROR: Failed to get myself timespec: %s\n", argv[0],
            EINVAL_STR);
            break;
        case ENOSYS:
            printf("%s: ERROR: Failed to get myself timespec: %s\n", argv[0],
            ENOSYS_STR);
            break;
        case ESRCH:
            printf("%s: ERROR: Failed to get myself timespec: %s\n", argv[0],
            ESRCH_STR);
            break;
        default:
            printf("%s: ERROR: Failed to get myself timespec\n", argv[0]);
            break;
        }
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
    return EXIT_SUCCESS;
}

接下來又查到一個有趣的東西。函數 strerror(int errnum) 這個函數需要在配置中開啓。位置: -> Library Routines -> Enable strerror 這樣就可以不用寫 switch 語句了。優化後的代碼:

#include <sched.h>
#include <nuttx/config.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

#define CONFIG_EXAMPLES_HELLO_TASK_PRIORITY  SCHED_PRIORITY_DEFAULT
#define CONFIG_EXAMPLES_HELLO_TASK_STACKSIZE 2048

int hello_task_main(int argc, char *argv[]) {

    int ret;
    struct timespec hello_task_timespec;
    pid_t hello_task_pid;

    hello_task_pid = getpid();
    ret = sched_rr_get_interval(hello_task_pid, &hello_task_timespec);
    if (ret == 0) {
        printf("%s: Get myself timespec success\n", argv[0]);
        printf("%s:\nMy timespec:\n  tv_sec:  %d\n  tv_nsec: %d\n", argv[0], hello_task_timespec.tv_sec, hello_task_timespec.tv_nsec);
    } else {
        int errcode = errno;
        printf("%s: ERROR: Failed to get myself timespec: %s\n", argv[0], strerror(errcode));
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
    return EXIT_SUCCESS;
}

一下子就精簡了很多。結果:

nsh> hello_task
hello_task: Get myself timespec success
hello_task:                    
My timespec:                
  tv_sec:  0
  tv_nsec: 200000000
nsh> 

雖然不知道是個什麼情況,但是已經成功了。


任務調度的接口試驗到此結束。

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