pthread_setschedparam函数用法详解
pthread_setschedparam函数简介
- 头文件包含
#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 );
- 编译链接选项
-pthread
pthread_setschedparam函数常见使用错误
- 链接错误
undefined reference to `pthread_setschedparam'
解决办法:添加链接选项
-pthread
- 编译错误
warning: implicit declaration of function ‘pthread_setschedparam’ [-Wimplicit-function-declaration]
解决办法:包含头文件
#include <pthread.h>
pthread_setschedparam函数详细描述
pthread_setschedparam ()函数设置线程thread 的调度策略和参数
policy为thread 指定新的调度策略。policy 支持的值及其语义在sched (7)中描述
param指向的结构为thread 指定了新的调度参数,调度参数在以下结构中维护:
struct sched_param {
int sched_priority; /* Scheduling priority */
};
可以看到,只支持一个调度参数。有关每个调度策略中调度优先级的允许范围的详细信息,请参阅sched (7)
pthread_getschedparam ()函数返回policy和param 分别指向的缓冲区中线程thread 的调度策略和参数。返回的优先级值是由最近影响thread 的pthread_setschedparam ()、pthread_setschedprio (3)或pthread_create (3)调用设置的。返回的优先级不反映由于调用任何优先级继承或优先级上限函数(例如,请参见pthread_mutexattr_setprioceiling (3)和pthread_mutexattr_setprotocol (3)))而导致的任何临时优先级调整
pthread_setschedparam函数返回值
如果成功,这些函数返回0;错误时,它们返回一个非零错误号。如果pthread_setschedparam ()失败,则不更改thread的调度策略和参数。
pthread_setschedparam函数错误码
这两个函数都可能失败,并出现以下错误:
- 找不到ID为thread的线程。
pthread_setschedparam ()可能还会失败,并出现以下错误:
- EINVAL policy不是可识别的策略,或者param对policy 没有意义
- EPERM 调用方没有适当的权限来设置指定的调度策略和参数。
POSIX.1还记录了pthread_setschedparam ()的 ENOTSUP (“试图将策略或调度参数设置为不受支持的值”)错误
pthread_setschedparam函数其他说明
有关更改线程调度策略和优先级所需权限及其影响的说明,以及每个调度策略中优先级的允许范围的详细信息,请参阅sched (7)
pthread_setschedparam函数使用举例
下面的程序演示了pthread_setschedparam ()和pthread_getschedparam ()的使用,以及许多其他与调度相关的pthreads函数的使用。
在接下来的运行中,主线程将其调度策略设置为SCHED_FIFO,优先级为10,并初始化一个thread attributes对象,其调度策略属性为SCHED_RR,调度优先级属性为20。然后程序使用pthread_attr_setinheritsched (3))将thread attributes对象的inherit scheduler属性设置为PTHREAD_EXPLICIT_SCHED ,这意味着使用这个attributes对象创建的线程应该从thread attributes对象获取它们的调度属性。然后程序使用thread attributes对象创建一个线程,该线程显示其调度策略和优先级。
$ \fBsu\fP # Need privilege to set real-time scheduling policies
Password:
# \fB./a.out \-mf10 \-ar20 \-i e\fP
Scheduler settings of main thread
policy=SCHED_FIFO, priority=10
Scheduler settings in \(aqattr\(aq
policy=SCHED_RR, priority=20
inheritsched is EXPLICIT
Scheduler attributes of new thread
policy=SCHED_RR, priority=20
在上面的输出中,可以看到调度策略和优先级取自thread attributes对象中指定的值。
下一次运行与上一次运行相同,只是将inherit scheduler属性设置为PTHREAD_INHERIT_SCHED ,这意味着使用thread attributes对象创建的线程应该忽略attributes对象中指定的调度属性,而是从创建线程中获取它们的调度属性。
# \fB./a.out \-mf10 \-ar20 \-i i\fP
Scheduler settings of main thread
policy=SCHED_FIFO, priority=10
Scheduler settings in \(aqattr\(aq
policy=SCHED_RR, priority=20
inheritsched is INHERIT
Scheduler attributes of new thread
policy=SCHED_FIFO, priority=10
在上面的输出中,可以看到调度策略和优先级来自创建线程,而不是thread attributes对象。
请注意,如果我们省略了"-i\ i"选项,那么输出将是相同的,因为PTHREAD_INHERIT_SCHED是inherit scheduler属性的默认值。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) \e
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]\en", prog_name);
fprintf(stderr, "Options are:\en");
#define fpe(msg) fprintf(stderr, "\et%s", msg); /* Shorter */
fpe("\-a<policy><prio> Set scheduling policy and priority in\en");
fpe(" thread attributes object\en");
fpe(" <policy> can be\en");
fpe(" f SCHED_FIFO\en");
fpe(" r SCHED_RR\en");
fpe(" o SCHED_OTHER\en");
fpe("\-A Use default thread attributes object\en");
fpe("\-i {e|i} Set inherit scheduler attribute to\en");
fpe(" \(aqexplicit\(aq or \(aqinherit\(aq\en");
fpe("\-m<policy><prio> Set scheduling policy and priority on\en");
fpe(" main thread before pthread_create() call\en");
exit(EXIT_FAILURE);
}
static int
get_policy(char p, int *policy)
{
switch (p) {
case \(aqf\(aq: *policy = SCHED_FIFO; return 1;
case \(aqr\(aq: *policy = SCHED_RR; return 1;
case \(aqo\(aq: *policy = SCHED_OTHER; return 1;
default: return 0;
}
}
static void
display_sched_attr(int policy, struct sched_param *param)
{
printf(" policy=%s, priority=%d\en",
(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, ¶m);
if (s != 0)
handle_error_en(s, "pthread_getschedparam");
printf("%s\en", msg);
display_sched_attr(policy, ¶m);
}
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 \(aqa\(aq: attr_sched_str = optarg; break;
case \(aqA\(aq: use_null_attrib = 1; break;
case \(aqi\(aq: inheritsched_str = optarg; break;
case \(aqm\(aq: main_sched_str = optarg; break;
default: usage(argv[0], "Unrecognized option\en");
}
}
if (use_null_attrib &&
(inheritsched_str != NULL || attr_sched_str != NULL))
usage(argv[0], "Can\(aqt specify \-A with \-i or \-a\en");
/* 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)\en");
param.sched_priority = strtol(&main_sched_str[1], NULL, 0);
s = pthread_setschedparam(pthread_self(), policy, ¶m);
if (s != 0)
handle_error_en(s, "pthread_setschedparam");
}
display_thread_sched_attr("Scheduler settings of main thread");
printf("\en");
/* 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] == \(aqe\(aq)
inheritsched = PTHREAD_EXPLICIT_SCHED;
else if (inheritsched_str[0] == \(aqi\(aq)
inheritsched = PTHREAD_INHERIT_SCHED;
else
usage(argv[0], "Value for \-i must be \(aqe\(aq or \(aqi\(aq\en");
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 \(aqattr\(aq (\-a)\en");
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, ¶m);
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, ¶m);
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 \(aqattr\(aq\en");
display_sched_attr(policy, ¶m);
s = pthread_attr_getinheritsched(&attr, &inheritsched);
printf(" inheritsched is %s\en",
(inheritsched == PTHREAD_INHERIT_SCHED) ? "INHERIT" :
(inheritsched == PTHREAD_EXPLICIT_SCHED) ? "EXPLICIT" :
"???");
printf("\en");
}
/* 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);
}
评论区