Linux 不同调度方式的线程创建和应用

 一,线程相关函数和属性

创建线程函数

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,&param);进行获取对应参数

通过int pthread_attr_set*(&attr,&param);设置对应参数

线程分离状态: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);

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值