一,线程相关函数和属性
创建线程函数
int pthread_create (pthread_t* restrictthread, const pthread_attr_t* restrictattr,void* (*start_routine) (void*), void* restrict arg);
的第二个參数即为线程属性,传空指针表示使用缺省属性。
线程属性为一个结构体。详细例如以下
typedef struct
{
int detachstate; //线程的分离状态
int schedpolicy; //线程调度策略
structsched_param schedparam; //线程的调度參数
int inheritsched; //线程的继承性
int scope; //线程的作用域
size_t guardsize; //线程栈末尾的警戒缓冲区大小
void* stackaddr; //线程栈的位置
size_t stacksize; //线程栈的大小
}pthread_attr_t;
int pthread_attr_init(&attr);pthread_attr_t结构所包含的内容就是操作系统实现支持的线程所有属性的默认值。去初始化值pthread_attr_destroy(pthread_attr_t*attr);
通过int pthread_attr_get*(&attr,¶m);进行获取对应参数
通过int pthread_attr_set*(&attr,¶m);设置对应参数
线程分离状态:detachstate(pthread_attr_setdetachstate)
该属性决定了线程运行任务后以什么方式来结束自己。
方式如下:
(1) PTHREAD_CREATE_DETACHED —— 分离线程
置为分离线程的线程。当不须要被不论什么线程等待,线程运行完任务后,自己自己主动结束线程,并释放资源,父线程在创建子线程之后,,父线程不会去等待子线程结束再去运行自己接下来的程序;
(2) PTHREAD_CREATE_JOINABLE(缺省) —— 可汇合线程
可汇合线程为线程的默认状态,这样的情况下,原有的线程等待创建的线程结束。仅仅有当pthread_join()函数返回时。创建的线程才算终止。才干释放自己占用的系统资源。父线程会等待子线程运行结束,才继续运行接下来的程序。
线程的调度策略:schedpolicy(pthread_attr_setschedpolicy)
linux内核的三种调度方法:
1,SCHED_OTHER(0) 分时调度策略,
2,SCHED_FIFO(1)实时调度策略,先到先服务
3,SCHED_RR(2)实时调度策略,时间片轮转
线程的继承性: inheritsched(pthread_attr_setinheritsched)
(1) PTHREAD_INHERIT_SCHED(缺省) —— 调度属性自创建者线程继承
(2) PTHREAD_EXPLICIT_SCHED —— 调度属性由调度參数和调度策略决定
(调整inheritsched 需要root权限执行才能创建线程成功,否则产生返回值为1的错误)
调度优先级參数 :struct sched_param schedparamer
结构sched_param的子成员sched_priority控制一个优先权值,大的优先权值相应高的优先权。
系统支持的最大和最小优先权值能够用sched_get_priority_max函数和sched_get_priority_min函数分别得到,通过pthread_attr_setschedparam(&attr, &schedparamer)设置。
线程的作用域 scope:参数设置的是线程优先级的使用范围。
PTHREAD_SCOPE_PROCESS 进程级竞争资源
PTHREAD_SCOPE_SYSTEM 系统级竞争资源
线程名称:
pthread_setname_nppthread_setname_np(pthread_t restrictthread, (const char*)pthName);
必须在生成线程后设置有效,建议在线程内设置。
取消线程:
int pthread_cancel(pthread_t restrictthread);注意在线程取消点退出,需要释放资源。
等待线程结束:
int pthread_join(pthread_t restrictthread, NULL); 调用后一直block住,一直等到线程被结束以后才退出。
二,SCHED_OTHER/SCHED_FIFO/SCHED_RR不同调度方式创建线程,比如SCHED_OTHER里创建SCHED_RR和SCHED_RR里创建SCHED_OTHER需要注意如下:
(1)SCHED_RR(SCHED_FIFO)里创建SCHED_OTHER
SCHED_OTHER线程优先级schedparamer.sched_priority必须为0,并且不能继承PTHREAD_EXPLICIT_SCHED。SCHED_OTHER线程优先级sched_get_priority_min:0;sched_get_priority_max:0;
(2),SCHED_OTHER里创建SCHED_RR(SCHED_FIFO)
SCHED_RR(SCHED_FIFO)线程优先级schedparamer.sched_priority必须为1~99,值越大优先级越高,并且不能继承PTHREAD_EXPLICIT_SCHED。SCHED_RR(SCHED_FIFO)线程优先级sched_get_priority_min:1;sched_get_priority_max:99;
(3),线程交叉创建如下:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/syscall.h>
typedef struct
{
char parentName[32];
char threadName[32];
int policy;
int priority;
void *parm;
void (*Fun)(void*);
} thread_routine_t;
/* pthread routine function,pthread name in trace */
static void *routine_function (thread_routine_t *pRoutine,char *p_name,int lwpid)
{
if (pRoutine && pRoutine->Fun)
{
printf("pthread [%s] Lwpid[%ld] start run .....\n",p_name,lwpid);
pRoutine->Fun(pRoutine->parm);
}
return NULL;
}
/* pthread start routine */
static void *start_routine (void *arg)
{
thread_routine_t *pRoutine = (thread_routine_t*)arg;
int lwpId = 0;
if(pRoutine && pRoutine->Fun)
{
lwpId = syscall(SYS_gettid);
routine_function (pRoutine,pRoutine->threadName,lwpId);
}
return NULL;
}
static void *create_thread_function(thread_routine_t *p_routine)
{
int ret = -1;
int min_proi = 0;
int max_proi = 0;
int def_proi = 0;
int inher = 0;
pthread_t thread_id = -1;
pthread_attr_t attr = {0};
struct sched_param schedparamer = {0};
int lwpId = 0;
int curr_policy = 0;
int selfId = 0;
selfId = pthread_self();
lwpId = syscall(SYS_gettid);
printf("[%s]thread id:0x%x;lwpid:0x%x \n",p_routine->parentName,selfId,lwpId);
curr_policy = sched_getscheduler(lwpId);
printf("###curr[%s]thread setscheduler[%d];RR[%d];FIFO:%d,OTHER:%d\n",p_routine->parentName,
curr_policy,SCHED_RR,SCHED_FIFO,SCHED_OTHER);
pthread_attr_init(&attr);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_attr_getinheritsched(&attr, &inher);
if(inher != PTHREAD_EXPLICIT_SCHED)
{
printf("change to PTHREAD_EXPLICIT_SCHED inheritsched\n");
inher = PTHREAD_EXPLICIT_SCHED; /***PTHREAD_EXPLICIT_SCHED need root Permission***/
}
pthread_attr_setinheritsched(&attr,inher);
pthread_attr_setschedpolicy(&attr, p_routine->policy);
min_proi = sched_get_priority_min(p_routine->policy);
max_proi = sched_get_priority_max(p_routine->policy);
pthread_attr_getschedparam(&attr, &schedparamer);
def_proi = schedparamer.sched_priority;
schedparamer.sched_priority = p_routine->priority;
pthread_attr_setschedparam(&attr, &schedparamer);
printf("[%s] priority :min:%d;max:%d;default:%d,set:%d\n",p_routine->parentName,
min_proi,max_proi,def_proi,schedparamer.sched_priority);
printf("[%s] create pthread policy:%d;sched_priority:%d\n",
p_routine->parentName,p_routine->policy,schedparamer.sched_priority);
ret = pthread_create(&thread_id, &attr,start_routine, (void*)p_routine);
if(ret == 0)
{
printf("create [%s] pthread : 0x%x success\n",p_routine->threadName,thread_id);
}
else
{
printf("create [%s] pthread fail ret = %d !!!\n",p_routine->threadName,ret);
}
while(1)
{
sleep(2);
printf("###it is [%s] function...\n",p_routine->parentName);
}
return NULL;
}
static void *fifo_function(void *p)
{
int lwpId = 0;
int curr_policy = 0;
int selfId = 0;
selfId = pthread_self();
lwpId = syscall(SYS_gettid);
printf("fifo_function thread id:0x%x;lwpid:0x%x \n",selfId,lwpId);
curr_policy = sched_getscheduler(lwpId);
printf("###fifo_function thread setscheduler[%d];RR[%d];FIFO:%d,OTHER:%d\n",
curr_policy,SCHED_RR,SCHED_FIFO,SCHED_OTHER);
while(1)
{
sleep(2);
printf("###it is SCHED_FIFO thread function...\n");
}
return NULL;
}
static void *other_thread(void *p)
{
thread_routine_t routineparam = {0};
strcpy(routineparam.parentName,"other_thread");
strcpy(routineparam.threadName,"fifo_thread");
routineparam.policy = SCHED_FIFO;
routineparam.priority = 10;
routineparam.Fun = fifo_function;
create_thread_function((thread_routine_t *)&routineparam);
return NULL;
}
static void *rr_thread(void *p)
{
thread_routine_t routineparam = {0};
strcpy(routineparam.parentName,"rr_thread");
strcpy(routineparam.threadName,"other_thread");
routineparam.policy = SCHED_OTHER;
routineparam.priority = 0;
routineparam.Fun = other_thread;
create_thread_function((thread_routine_t *)&routineparam);
return NULL;
}
int main(int argc, char **argv)
{
thread_routine_t routineparam = {0};
strcpy(routineparam.parentName,"main");
strcpy(routineparam.threadName,"rr_thread");
routineparam.policy = SCHED_RR;
routineparam.priority = 90;
routineparam.Fun = rr_thread;
create_thread_function((thread_routine_t *)&routineparam);
return 0;
}
编译:gcc -o test test_threard.c -lpthread
测试:sudo ./test(必须root 权限,否则因为inheritsched 改变而无法创建线程成功)
三,线程的相关控制
线程互斥锁:mutex
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
或pthread_mutex_init(&mutex, NULL);初始化
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
pthread_mutex_destroy(&mutex); 注销互斥锁
线程条件控制:cond
pthread_condattr_t cattr;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;/*初始化条件变量*/
pthread_condattr_init(&cattr);
pthread_condattr_setclock(&cattr, CLOCK_MONOTONIC);
pthread_cond_init(&cond, &cattr);
pthread_cond_timedwait(&cond, &mutex, &waittime);超时等待
pthread_cond_wait(&cond,&mutex);/*解锁mutex,并等待cond改变,改变后加锁mutex。
pthread_cond_signal(&cond);/*条件改变,发送信号
pthread_cond_destroy(&cond);