PTHREAD_SETSCHEDPARAM - Linux手册页

时间:2019-08-20 18:01:03  来源:igfitidea点击:

Linux程序员手册 第3部分
更新日期: 2020-06-09

名称

pthread_setschedparam,pthread_getschedparam-设置/获取线程的调度策略和参数

语法

#include <pthread.h>

int pthread_setschedparam(pthread_t thread, int policy,
                          const struct sched_param *param);
int pthread_getschedparam(pthread_t thread, int *policy,
                          struct sched_param *param);

Compile and link with -pthread.

说明

pthread_setschedparam()函数设置线程线程的调度策略和参数。

policy为线程指定新的调度策略。 sched(7)中描述了策略支持的值及其语义。

param指向的结构为线程指定了新的调度参数。调度参数以以下结构维护:

struct sched_param {
    int sched_priority;     /* Scheduling priority */
};

可以看出,仅支持一个调度参数。有关每个调度策略中调度优先级的允许范围的详细信息,请参见sched(7)。

pthread_getschedparam()函数分别在policy和param指向的缓冲区中返回线程线程的调度策略和参数。返回的优先级值是由受影响线程的最新pthread_setschedparam(),pthread_setschedprio(3)或pthread_create(3)调用设置的值。由于调用任何优先级继承或优先级上限函数,返回的优先级不反映任何临时的优先级调整(例如,请参见pthread_mutexattr_setprioceiling(3)和pthread_mutexattr_setprotocol(3))。

返回值

成功时,这些函数返回0;否则,返回0。错误时,它们返回非零错误号。如果pthread_setschedparam()失败,则不会更改线程的调度策略和参数。

错误说明

这两个功能都可能由于以下错误而失败:

ESRCH
找不到具有ID线程的线程。

pthread_setschedparam()可能还会因以下错误而失败:

EINVAL
策略不是公认的策略,或者参数对于该策略没有意义。
EPERM
调用者没有适当的特权来设置指定的调度策略和参数。

POSIX.1还记录了pthread_setschedparam()的ENOTSUP("尝试将策略或调度参数设置为不受支持的值")错误。

属性

有关本节中使用的术语的说明,请参见attribute(7)。

InterfaceAttributeValue
pthread_setschedparam(),pthread_getschedparam()Thread safetyMT-Safe

遵循规范

POSIX.1-2001,POSIX.1-2008。

备注

有关更改线程的调度策略和优先级所需的权限以及其效果的说明,以及每种调度策略中优先级的允许范围的详细信息,请参见sched(7)。

示例

下面的程序演示了pthread_setschedparam()和pthread_getschedparam()的用法,以及许多其他与调度相关的pthreads函数的用法。

在下面的运行中,主线程将其调度策略设置为SCHED_FIFO,优先级为10,并初始化一个线程属性对象,该对象的调度策略属性为SCHED_RR,调度优先级属性为20。然后,程序将设置(使用pthread_attr_setinheritsitsched(3 ))线程属性对象的继承调度程序属性为PTHREAD_EXPLICIT_SCHED,这意味着使用此属性对象创建的线程应从线程属性对象获取其调度属性。然后程序使用线程属性对象创建一个线程,该线程显示其调度策略和优先级。

$ su      # Need privilege to set real-time scheduling policies
Password:
# ./a.out -mf10 -ar20 -i e
Scheduler settings of main thread
    policy=SCHED_FIFO, priority=10

Scheduler settings in aqattraq
    policy=SCHED_RR, priority=20
    inheritsched is EXPLICIT

Scheduler attributes of new thread
    policy=SCHED_RR, priority=20

在上面的输出中,可以看到调度策略和优先级来自线程属性对象中指定的值。

下次运行与上一次相同,不同之处是将继承调度程序属性设置为PTHREAD_INHERIT_SCHED,这意味着使用线程属性对象创建的线程应忽略在属性对象中指定的调度属性,而是从创建线程中获取其调度属性。

# ./a.out -mf10 -ar20 -i i
Scheduler settings of main thread
    policy=SCHED_FIFO, priority=10

Scheduler settings in aqattraq
    policy=SCHED_RR, priority=20
    inheritsched is INHERIT

Scheduler attributes of new thread
    policy=SCHED_FIFO, priority=10

在上面的输出中,可以看到调度策略和优先级是从创建线程获取的,而不是线程属性对象。

请注意,如果我们省略了-i选项,则输出将是相同的,因为PTHREAD_INHERIT_SCHED是继承调度程序属性的默认值。

Program source

/* pthreads_sched_test.c */

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

#define handle_error_en(en, msg) \
        do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

static void
usage(char *prog_name, char *msg)
{
    if (msg != NULL)
        fputs(msg, stderr);

    fprintf(stderr, "Usage: %s [options]\n", prog_name);
    fprintf(stderr, "Options are:\n");
#define fpe(msg) fprintf(stderr, "\t%s", msg);          /* Shorter */
    fpe("-a<policy><prio> Set scheduling policy and priority in\n");
    fpe("                 thread attributes object\n");
    fpe("                 <policy> can be\n");
    fpe("                     f  SCHED_FIFO\n");
    fpe("                     r  SCHED_RR\n");
    fpe("                     o  SCHED_OTHER\n");
    fpe("-A               Use default thread attributes object\n");
    fpe("-i {e|i}         Set inherit scheduler attribute to\n");
    fpe("                 aqexplicitaq or aqinheritaq\n");
    fpe("-m<policy><prio> Set scheduling policy and priority on\n");
    fpe("                 main thread before pthread_create() call\n");
    exit(EXIT_FAILURE);
}

static int
get_policy(char p, int *policy)
{
    switch (p) {
    case aqfaq: *policy = SCHED_FIFO;     return 1;
    case aqraq: *policy = SCHED_RR;       return 1;
    case aqoaq: *policy = SCHED_OTHER;    return 1;
    default:  return 0;
    }
}

static void
display_sched_attr(int policy, struct sched_param *param)
{
    printf("    policy=%s, priority=%d\n",
            (policy == SCHED_FIFO)  ? "SCHED_FIFO" :
            (policy == SCHED_RR)    ? "SCHED_RR" :
            (policy == SCHED_OTHER) ? "SCHED_OTHER" :
            "???",
            param->sched_priority);
}

static void
display_thread_sched_attr(char *msg)
{
    int policy, s;
    struct sched_param param;

    s = pthread_getschedparam(pthread_self(), &policy, &param);
    if (s != 0)
        handle_error_en(s, "pthread_getschedparam");

    printf("%s\n", msg);
    display_sched_attr(policy, &param);
}

static void *
thread_start(void *arg)
{
    display_thread_sched_attr("Scheduler attributes of new thread");

    return NULL;
}

int
main(int argc, char *argv[])
{
    int s, opt, inheritsched, use_null_attrib, policy;
    pthread_t thread;
    pthread_attr_t attr;
    pthread_attr_t *attrp;
    char *attr_sched_str, *main_sched_str, *inheritsched_str;
    struct sched_param param;

    /* Process command-line options */

    use_null_attrib = 0;
    attr_sched_str = NULL;
    main_sched_str = NULL;
    inheritsched_str = NULL;

    while ((opt = getopt(argc, argv, "a:Ai:m:")) != -1) {
        switch (opt) {
        case aqaaq: attr_sched_str = optarg;      break;
        case aqAaq: use_null_attrib = 1;          break;
        case aqiaq: inheritsched_str = optarg;    break;
        case aqmaq: main_sched_str = optarg;      break;
        default:  usage(argv[0], "Unrecognized option\n");
        }
    }

    if (use_null_attrib &&
            (inheritsched_str != NULL || attr_sched_str != NULL))
        usage(argv[0], "Canaqt specify -A with -i or -a\n");

    /* Optionally set scheduling attributes of main thread,
       and display the attributes */

    if (main_sched_str != NULL) {
        if (!get_policy(main_sched_str[0], &policy))
            usage(argv[0], "Bad policy for main thread (-m)\n");
        param.sched_priority = strtol(&main_sched_str[1], NULL, 0);

        s = pthread_setschedparam(pthread_self(), policy, &param);
        if (s != 0)
            handle_error_en(s, "pthread_setschedparam");
    }

    display_thread_sched_attr("Scheduler settings of main thread");
    printf("\n");

    /* Initialize thread attributes object according to options */

    attrp = NULL;

    if (!use_null_attrib) {
        s = pthread_attr_init(&attr);
        if (s != 0)
            handle_error_en(s, "pthread_attr_init");
        attrp = &attr;
    }

    if (inheritsched_str != NULL) {
        if (inheritsched_str[0] == aqeaq)
            inheritsched = PTHREAD_EXPLICIT_SCHED;
        else if (inheritsched_str[0] == aqiaq)
            inheritsched = PTHREAD_INHERIT_SCHED;
        else
            usage(argv[0], "Value for -i must be aqeaq or aqiaq\n");

        s = pthread_attr_setinheritsched(&attr, inheritsched);
        if (s != 0)
            handle_error_en(s, "pthread_attr_setinheritsched");
    }

    if (attr_sched_str != NULL) {
        if (!get_policy(attr_sched_str[0], &policy))
            usage(argv[0],
                    "Bad policy for aqattraq (-a)\n");
        param.sched_priority = strtol(&attr_sched_str[1], NULL, 0);

        s = pthread_attr_setschedpolicy(&attr, policy);
        if (s != 0)
            handle_error_en(s, "pthread_attr_setschedpolicy");
        s = pthread_attr_setschedparam(&attr, &param);
        if (s != 0)
            handle_error_en(s, "pthread_attr_setschedparam");
    }

    /* If we initialized a thread attributes object, display
       the scheduling attributes that were set in the object */

    if (attrp != NULL) {
        s = pthread_attr_getschedparam(&attr, &param);
        if (s != 0)
            handle_error_en(s, "pthread_attr_getschedparam");
        s = pthread_attr_getschedpolicy(&attr, &policy);
        if (s != 0)
            handle_error_en(s, "pthread_attr_getschedpolicy");

        printf("Scheduler settings in aqattraq\n");
        display_sched_attr(policy, &param);

        s = pthread_attr_getinheritsched(&attr, &inheritsched);
        printf("    inheritsched is %s\n",
                (inheritsched == PTHREAD_INHERIT_SCHED)  ? "INHERIT" :
                (inheritsched == PTHREAD_EXPLICIT_SCHED) ? "EXPLICIT" :
                "???");
        printf("\n");
    }

    /* Create a thread that will display its scheduling attributes */

    s = pthread_create(&thread, attrp, &thread_start, NULL);
    if (s != 0)
        handle_error_en(s, "pthread_create");

    /* Destroy unneeded thread attributes object */

    if (!use_null_attrib) {
      s = pthread_attr_destroy(&attr);
      if (s != 0)
          handle_error_en(s, "pthread_attr_destroy");
    }

    s = pthread_join(thread, NULL);
    if (s != 0)
        handle_error_en(s, "pthread_join");

    exit(EXIT_SUCCESS);
}

另外参见

getrlimit(2),sched_get_priority_min(2),pthread_attr_init(3),pthread_attr_setinheritsched(3),pthread_attr_setschedparam(3),pthread_attr_setschedpolicy(3),pthread_create(3),pthread_self(3),pthread_set(3),pthread_set(3),pthread_set(s)预定(7)

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/