如果创建的线程不够多,有些问题是体现不出来的。
优先级打印:
测试目的:输出三种调度模式下的最大优先级和最小优先级
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#include <sys/select.h>
#include <sys/epoll.h>
#include <errno.h>
#include <sys/wait.h>
#include <netinet/tcp.h>
#define DEBUG_INFO(format, ...) printf("%s:%d -- " format "\n", __func__, __LINE__,##__VA_ARGS__)
int main(){
int min;
int max;
min = sched_get_priority_min(SCHED_OTHER);
max = sched_get_priority_max(SCHED_OTHER);
DEBUG_INFO("SCHED_OTHER min = %d,max = %d",min,max);
min = sched_get_priority_min(SCHED_RR);
max = sched_get_priority_max(SCHED_RR);
DEBUG_INFO("SCHED_RR min = %d,max = %d",min,max);
min = sched_get_priority_min(SCHED_FIFO);
max = sched_get_priority_max(SCHED_FIFO);
DEBUG_INFO("SCHED_FIFO min = %d,max = %d",min,max);
return 0;
}
执行结果:
main:25 -- SCHED_OTHER min = 0,max = 0
main:29 -- SCHED_OTHER min = 1,max = 99
main:33 -- SCHED_OTHER min = 1,max = 99
测试一:先创建10个线程。
使用默认属性。
#include <stdio.h>
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#include <signal.h>
#include <map>
#define DEBUG_INFO(format, ...) printf("%s:%d -- " format "\n", __func__, __LINE__,##__VA_ARGS__)
std::map<pthread_t ,int> thread_index_map;
struct mystruct{
int index;
pthread_t thread;
};
void clean_up_resource(void *arg){
struct mystruct *pms = (struct mystruct *)arg;
DEBUG_INFO("delete thread index = %d\n", pms->index);
free(arg);
}
void *func(void *arg){
struct mystruct *pms = (struct mystruct *)arg;
static pthread_t thread_id = pthread_self();
pthread_cleanup_push(clean_up_resource,arg);
while(1){
for(int i = 0;i < 10000000;i++){
}
break;
}
DEBUG_INFO("index = %d",pms->index);
return 0;
pthread_cleanup_pop(0);
}
int main(int argc, char**){
for(int i=0; i < 10; i++){
pthread_t t;
struct mystruct *pms = (struct mystruct*)malloc(sizeof(struct mystruct));
pms->index = i;
int ret = pthread_create(&t, NULL, func,pms);
if(ret != 0){
perror("pthread_create");
}
}
while(1){
sleep(1);
}
}
执行结果:
main:44 -- pid = 39495
func:37 -- index = 3
func:37 -- index = 8
func:37 -- index = 0
func:37 -- index = 4
func:37 -- index = 6
func:37 -- index = 9
func:37 -- index = 2
func:37 -- index = 7
func:37 -- index = 5
func:37 -- index = 1
pstree -p命令的执行截图
上面我们看到输出的index的值,不是倒叙也不是正序,而是乱序的,现在,我们需要设置线程的优先级,让他们有序的运行,如何操作呢。
测试二:线程的清理
捕获信号SIGINT,在SIGINT信号处理函数中,结束10个线程。然后
#include <stdio.h>
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#include <signal.h>
#include <map>
#include <list>
#define DEBUG_INFO(format, ...) printf("%s:%d -- " format "\n", __func__, __LINE__,##__VA_ARGS__)
std::map<pthread_t ,int> thread_index_map;
typedef void (*sighandler)(int signo);
struct mystruct{
int index;
pthread_t thread;
};
void clean_up_resource(void *arg){
struct mystruct *pms = (struct mystruct *)arg;
DEBUG_INFO("delete thread index = %d\n", pms->index);
free(arg);
}
std::list<pthread_t> pthread_list;
void *func(void *arg){
pthread_list.push_back(pthread_self());
struct mystruct *pms = (struct mystruct *)arg;
static pthread_t thread_id = pthread_self();
pthread_cleanup_push(clean_up_resource,arg);
while(1){
for(int i = 0;i < 10000000;i++){
}
break;
}
DEBUG_INFO("index = %d",pms->index);
while(1)sleep(1);
return 0;
pthread_cleanup_pop(0);
}
void sig_func(int signo){
auto it = pthread_list.begin();
DEBUG_INFO("%lu",pthread_list.size());
for(;it != pthread_list.end();it++){
pthread_cancel(*it);
}
DEBUG_INFO("good bye");
sleep(2);
exit(0);
}
int main(int argc, char**){
sighandler sig_ret;
sig_ret = signal(SIGINT, sig_func);
if(sig_ret == SIG_ERR){
perror("signal");
exit(-1);
}
DEBUG_INFO("pid = %u",getpid());
for(int i=0; i < 10; i++){
pthread_t t;
struct mystruct *pms = (struct mystruct*)malloc(sizeof(struct mystruct));
pms->index = i;
int ret = pthread_create(&t, NULL, func,pms);
if(ret != 0){
perror("pthread_create");
}
}
while(1){
sleep(1);
}
return 0;
}
执行结果:
main:65 -- pid = 50827
func:39 -- index = 1
func:39 -- index = 4
func:39 -- index = 2
func:39 -- index = 3
func:39 -- index = 0
func:39 -- index = 5
func:39 -- index = 6
func:39 -- index = 8
func:39 -- index = 7
func:39 -- index = 9
^Csig_func:49 -- 10
sig_func:53 -- good bye
clean_up_resource:23 -- delete thread index = 0
clean_up_resource:23 -- delete thread index = 4
clean_up_resource:23 -- delete thread index = 1
clean_up_resource:23 -- delete thread index = 3
clean_up_resource:23 -- delete thread index = 5
clean_up_resource:23 -- delete thread index = 8
clean_up_resource:23 -- delete thread index = 9
clean_up_resource:23 -- delete thread index = 2
clean_up_resource:23 -- delete thread index = 7
clean_up_resource:23 -- delete thread index = 6
按下CTRL+C后,sig_func被执行,开始遍历删除链表中的线程。最后退出进程。为了让删除动作成功完成,执行exit(0)之前先休眠2秒。
测试三:线程的属性
pthread_attr_init函数
NAME
pthread_attr_init, pthread_attr_destroy - initialize and destroy thread attributes object
SYNOPSIS
#include <pthread.h>
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);
Compile and link with -pthread.
pthread_getattr_np函数
NAME
pthread_getattr_np - get attributes of created thread
SYNOPSIS
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <pthread.h>
int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr);
Compile and link with -pthread.
pthread_attr_t结构体
pthread_attr_init函数
NAME
pthread_attr_init, pthread_attr_destroy - initialize and destroy thread attributes object
SYNOPSIS
#include <pthread.h>
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);
Compile and link with -pthread.
线程的优先级是经常设置的属性,由两个函数进行控制:pthread_attr_getschedparam()函数获得线程的优先级设置;函数pthread_attr_setschedparam()设置线程的优先级。
pthread_attr_setschedparam函数
NAME
pthread_attr_setschedparam, pthread_attr_getschedparam - set/get scheduling parameter attributes in thread attributes object
SYNOPSIS
#include <pthread.h>
int pthread_attr_setschedparam(pthread_attr_t *attr,
const struct sched_param *param);
int pthread_attr_getschedparam(const pthread_attr_t *attr,
struct sched_param *param);
Compile and link with -pthread.
结构体struct sched_param
struct sched_param {
int sched_priority; /* Scheduling priority */
};
pthread_testcancel函数
NAME
pthread_testcancel - request delivery of any pending cancellation request
SYNOPSIS
#include <pthread.h>
void pthread_testcancel(void);
Compile and link with -pthread.
schedpolicy:这个属性控制线程的调度方式。它的取值可以是SCHED_OTHER、SCHED_RP和SCHED_FIFO。这个属性的默认值为SCHED_OTHER。另外两种调度方式只能用于以超级用户权限运行的进程,因为它们都具备实时调度的功能,但在行为上略有区别。SCHED_RP使用循环(round-robin)调度机制,而SCHED_FIFO使用“先进先出”策略。
测试三:优先级测试
#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* To get pthread_getattr_np() declaration */
#endif
#define _REENTRANT
#include <stdio.h>
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#include <signal.h>
#include <map>
#include <list>
#include <sched.h>
#include <atomic>
using namespace std;
#define DEBUG_INFO(format, ...) printf("%s:%d -- " format "\n", __func__, __LINE__,##__VA_ARGS__)
std::map<pthread_t ,int> thread_index_map;
typedef void (*sighandler)(int signo);
struct mystruct{
int index;
pthread_t thread;
pthread_attr_t attr;
struct sched_param sched;
};
void clean_up_resource(void *arg){
struct mystruct *pms = (struct mystruct *)arg;
DEBUG_INFO("delete thread index = %d\n", pms->index);
pthread_attr_destroy(&pms->attr);
free(arg);
}
std::list<pthread_t> pthread_list;
// std::atomic_bool start = false;
atomic<long> start(0);
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *func(void *arg){
pthread_list.push_back(pthread_self());
struct mystruct *pms = (struct mystruct *)arg;
static pthread_t thread_id = pthread_self();
pthread_cleanup_push(clean_up_resource,arg);
// pthread_mutex_lock(&mtx);
// while(start == 0){
// pthread_cond_wait(&cond,&mtx);
// }
// pthread_mutex_unlock(&mtx);
int ret = pthread_setschedparam(pthread_self(), SCHED_FIFO, &pms->sched);
if (ret != 0) {
perror("pthread_setschedparam");
exit(-1);
}
while(start == 0){}
DEBUG_INFO("start thread = %d",pms->index);
while(1){
for(int i = 0;i < 100;i++){
pthread_testcancel();
for(int j = 0;j < 100;j++){usleep(1);}
}
break;
}
DEBUG_INFO("index = %d",pms->index);
while(1)sleep(1);
return 0;
pthread_cleanup_pop(0);
}
void sig_func(int signo){
auto it = pthread_list.begin();
DEBUG_INFO("%lu",pthread_list.size());
for(;it != pthread_list.end();it++){
pthread_cancel(*it);
}
DEBUG_INFO("good bye");
sleep(2);
exit(0);
}
int main(int argc, char**){
sighandler sig_ret;
sig_ret = signal(SIGINT, sig_func);
if(sig_ret == SIG_ERR){
perror("signal");
exit(-1);
}
DEBUG_INFO("pid = %u",getpid());
for(int i=0; i < 10; i++){
pthread_t t;
struct mystruct *pms = (struct mystruct*)malloc(sizeof(struct mystruct));
if(!pms){
perror("malloc");
raise(SIGINT);
while(1)sleep(1);
}
pms->index = i;
pthread_attr_init(&pms->attr);
pthread_attr_getschedparam(&pms->attr,&pms->sched);
DEBUG_INFO("pms->sched.sched_priority = %d",pms->sched.sched_priority);
pthread_attr_setschedpolicy(&pms->attr,SCHED_FIFO);//SCHED_OTHER);//SCHED_RP);//SCHED_FIFO);
pms->sched.sched_priority = (i + 1)*5;
pthread_attr_setschedparam(&pms->attr,&pms->sched);
pthread_attr_getschedparam(&pms->attr,&pms->sched);
DEBUG_INFO("pms->sched.sched_priority = %d",pms->sched.sched_priority);
int ret = pthread_create(&t, NULL, func,pms);
if(ret != 0){
perror("malloc");
raise(SIGINT);
free(pms);
}
}
start = 1;
//pthread_cond_signal(&cond);
pthread_cond_broadcast(&cond);
while(1){
sleep(1);
}
return 0;
}
main:93 -- pid = 87681
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 5
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 10
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 15
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 20
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 25
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 30
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 35
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 40
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 45
main:106 -- pms->sched.sched_priority = 0
main:112 -- pms->sched.sched_priority = 50
func:59 -- start thread = 4
func:59 -- start thread = 0
func:59 -- start thread = 1
func:59 -- start thread = 3
func:59 -- start thread = 6
func:59 -- start thread = 5
func:59 -- start thread = 7
func:59 -- start thread = 9
func:59 -- start thread = 2
func:59 -- start thread = 8
func:68 -- index = 9
func:68 -- index = 6
func:68 -- index = 7
func:68 -- index = 8
func:68 -- index = 4
func:68 -- index = 2
func:68 -- index = 3
func:68 -- index = 5
func:68 -- index = 0
func:68 -- index = 1
线程9优先级最高,所以先执行完成,线程0优先级最低,倒数第二完成。只能说整体上能看出来是优先级的趋势是对的了。因为是多核的关系吗。所以不是纯正的降序。
在单核的ARM板上运行,如下所示,没有达到我心中的降序的效果啊。4都最先完成了。但是每次执行完成的数序确实固定的,这...
func:68 -- index = 4
func:68 -- index = 5
func:68 -- index = 6
func:68 -- index = 7
func:68 -- index = 3
func:68 -- index = 2
func:68 -- index = 8
func:68 -- index = 9
func:68 -- index = 1
func:68 -- index = 0
优化后的代码
#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* To get pthread_getattr_np() declaration */
#endif
#ifndef _REENTRANT
#define _REENTRANT
#endif
#include <stdio.h>
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#include <signal.h>
#include <map>
#include <list>
#include <sched.h>
#include <atomic>
using namespace std;
#define DEBUG_INFO(format, ...) printf("%s:%d -- " format "\n", __func__, __LINE__,##__VA_ARGS__)
std::map<pthread_t ,int> thread_index_map;
typedef void (*sighandler)(int signo);
struct mystruct{
int index;
pthread_t thread;
pthread_attr_t attr;
struct sched_param sched;
};
void clean_up_resource(void *arg){
struct mystruct *pms = (struct mystruct *)arg;
DEBUG_INFO("delete thread index = %d\n", pms->index);
pthread_attr_destroy(&pms->attr);
free(arg);
}
std::list<pthread_t> pthread_list;
// std::atomic_bool start = false;
atomic<long> start(0);
atomic<long> counter(0);
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *func(void *arg){
pthread_list.push_back(pthread_self());
struct mystruct *pms = (struct mystruct *)arg;
static pthread_t thread_id = pthread_self();
pthread_cleanup_push(clean_up_resource,arg);
// int ret = pthread_setschedparam(pthread_self(), SCHED_FIFO, &pms->sched);
// if (ret != 0) {
// perror("pthread_setschedparam");
// exit(-1);
// }
sched_setscheduler(pthread_self(), SCHED_FIFO,&pms->sched);//SCHED_FIFO//SCHED_RR(round-robin)
pthread_mutex_lock(&mtx);
while(start == 0){
pthread_cond_wait(&cond,&mtx);
}
pthread_mutex_unlock(&mtx);
DEBUG_INFO("start thread = %d",pms->index);
pthread_attr_getschedparam(&pms->attr,&pms->sched);
DEBUG_INFO("pms->sched.sched_priority = %d",pms->sched.sched_priority);
while(1){
for(int i = 0;i < 10000;i++){
//pthread_testcancel();
for(int j = 0;j < 10000;j++){counter++;}
}
break;
}
DEBUG_INFO("index = %d",pms->index);
while(1)sleep(1);
return 0;
pthread_cleanup_pop(0);
}
void sig_func(int signo){
auto it = pthread_list.begin();
DEBUG_INFO("%lu",pthread_list.size());
for(;it != pthread_list.end();it++){
pthread_cancel(*it);
}
DEBUG_INFO("good bye");
sleep(2);
std::cout << "counter = " << counter << std::endl;
exit(0);
}
int main(int argc, char**){
sighandler sig_ret;
sig_ret = signal(SIGINT, sig_func);
if(sig_ret == SIG_ERR){
perror("signal");
exit(-1);
}
DEBUG_INFO("pid = %u",getpid());
for(int i=0; i < 10; i++){
pthread_t t;
struct mystruct *pms = (struct mystruct*)malloc(sizeof(struct mystruct));
if(!pms){
perror("malloc");
raise(SIGINT);
while(1)sleep(1);
}
pms->index = i;
pthread_attr_init(&pms->attr);
pthread_attr_getschedparam(&pms->attr,&pms->sched);
DEBUG_INFO("pms->sched.sched_priority = %d",pms->sched.sched_priority);
pthread_attr_setschedpolicy(&pms->attr,SCHED_FIFO);//SCHED_OTHER);//SCHED_RP);//SCHED_FIFO);
pms->sched.sched_priority = 100 - (i + 1)*5;
pthread_attr_setschedparam(&pms->attr,&pms->sched);
pthread_attr_getschedparam(&pms->attr,&pms->sched);
DEBUG_INFO("pms->sched.sched_priority = %d",pms->sched.sched_priority);
int ret = pthread_create(&t, NULL, func,pms);
if(ret != 0){
perror("malloc");
raise(SIGINT);
free(pms);
}
}
start = 1;
//pthread_cond_signal(&cond);
pthread_cond_broadcast(&cond);
while(1){
sleep(1);
}
return 0;
}
测试结果略