• 【PTHREAD】线程属性


    1. 线程属性结构

    #  define __SIZEOF_PTHREAD_ATTR_T 56
    
    union pthread_attr_t
    {
      char __size[__SIZEOF_PTHREAD_ATTR_T];
      long int __align;
    };
    
    typedef union pthread_attr_t pthread_attr_t;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2. 初始化线程属性

    int pthread_attr_init(pthread_attr_t *attr);
    
    • 1
    • 以默认值的方式初始化线程属性对象。
    • 经过初始化后的线程属性对象可以使用不同的函数(pthread_attr_set*)设置对应的属性,最后将该属性用于pthread_create函数,用于创建具有指定属性的线程。
    • 调用该函数初始化一个已初始化的的线程属性对象,将导致不确定的行为。

    3. 销毁线程属性

    int pthread_attr_destroy(pthread_attr_t *attr);
    
    • 1
    • 销毁一个线程属性对象
    • 线程属性对象销毁后,不影响使用该属性创建的线程对象
    • 已销毁的线程属性对象,可以使用pthread_attr_init重新初始化
    • 使用一个已销毁的线程属性对象,将导致不确定的行为

    4. 线程属性之分离状态

    int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
    int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
    
    • 1
    • 2
    • 获取或设置线程属性对象中的线程分离状态。

    • 有两种状态值:

      • PTHREAD_CREATE_DETACHED
        使用该属性创建的线程,处于分离态
      • PTHREAD_CREATE_JOINABLE
        使用该属性创建的线程,处于关联态。默认值。
    • 拥有PTHREAD_CREATE_JOINABLE属性的线程,可通过pthread_detach修改为PTHREAD_CREATE_DETACHED。反之不可行。

    5. 线程属性之栈保护区尺寸

    int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
    int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize);
    
    • 1
    • 2
    • 如果该属性值大于零,则使用该属性创建的线程,在线程栈末尾多出一块至少guard size字节的保护区。
    • 如果该属性值等于零,则无线程栈保护区。
    • 默认保护大小与系统页面大小相同。
    • 如果使用pthread_attr_setstackpthread_attr_setstackaddr设置了线程属性对象的栈地址,则栈保护区大小被忽略。

    6. 线程属性之调度继承

    int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched);
    int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inheritsched);
    
    • 1
    • 2
    • 获取或设置线程线程对象中的继承线程调度属性。该属性指示使用该线程对象创建的线程是继承父线程的调度属性,还是线程属性对象中指定的调度属性。以下线程调度属性受该属性的影响:
      • 调度策略(pthread_attr_setschedpolicy
      • 调度优先级(pthread_attr_setschedparam
      • 调度作用域(pthread_attr_setscope
    • 继承调度属性支持以下值:
      • PTHREAD_INHERIT_SCHED
        继承父线程的调度属性。线程属性对象中的调度属性被忽略。默认值。
      • PTHREAD_EXPLICIT_SCHED
        使用该线程属性对象中的调度属性

    7. 线程属性之调度策略

    int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
    int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);
    
    • 1
    • 2
    • 调度器是一个内核组件,该组件决定哪一个可运行的线程将运行。每一个线程都有一个相关的调度策略,一个静态的调度优先级。调度器根据系统上所有线程的调度策略和调度优先级做出调度决定。
    • 对于正常调度策略(SCHED_OTHER, SCHED_IDLE, SCHED_BATCH),调度优先级不用于调度决定,必须设置为0
    • 对于实时调度策略(SCHED_FIFO, SCHED_RR),调度优先级的范围[1, 99],值越大,优先级越高。
    • 对于特殊的调度策略,可以使用sched_get_priority_min(2)sched_get_priority_max(2)获取调度优先级的上下限
    • 该属性支持以下值:
      • SCHED_FIFO
        先入先出调度策略。该值仅能用于线程调度优先级高于零的线程。这意味着,一旦具有SCHED_FIFO属性的线程处于可运行状态,它总是立即抢占正在运行的具有正常调度策略的线程。
        • SCHED_RR
          循环调度策略。该策略是SCHED_FIFO策略的加强版。
        • SCHED_OTHER
          默认调度策略。此时线程调度优先级必须为0

    8. 线程属性之调度参数

    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);
    
    struct sched_param {
        int sched_priority;     /* Scheduling priority */
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    9. 线程属性之调度作用域

    int pthread_attr_setscope(pthread_attr_t *attr, int scope);
    int pthread_attr_getscope(const pthread_attr_t *attr, int *scope);
    
    • 1
    • 2
    • PTHREAD_SCOPE_SYSTEM
      使用具有该属性的线程属性对象创建的线程将在系统级别上竞争资源。
    • PTHREAD_SCOPE_PROCESS
      使用具有该属性的线程属性对象创建的线程将在进程级别上竞争资源。

    10. 线程属性之线程栈

    // 栈地址与栈尺寸
    int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize);
    int pthread_attr_getstack(const pthread_attr_t *attr, void **stackaddr, size_t *stacksize);
    
    // 栈地址
    int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr);
    int pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr);
    
    // 栈尺寸
    int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
    int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    11. 案例:获取线程属性默认值

    • 源码

      #include 
      #include 
      #include 
      
      int main(int argc, char const *argv[])
      {
          pthread_attr_t attr;
          pthread_attr_init(&attr);
      
          {
              int detech_state = 0;
              pthread_attr_getdetachstate(&attr, &detech_state);
              printf("default: detech state   = %s\n",
                     detech_state == PTHREAD_CREATE_DETACHED ? "PTHREAD_CREATE_DETACHED" :
                     detech_state == PTHREAD_CREATE_JOINABLE ? "PTHREAD_CREATE_JOINABLE" : "???");
          }
      
          {
              size_t guard_size = 0;
              pthread_attr_getguardsize(&attr, &guard_size);
              printf("default: guard size     = %lu\n", guard_size);
          }
      
          {
              int inherit_sched = 0;
              pthread_attr_getinheritsched(&attr, &inherit_sched);
              printf("default: inherit sched  = %s\n",
                     inherit_sched == PTHREAD_INHERIT_SCHED ? "PTHREAD_INHERIT_SCHED" :
                     inherit_sched == PTHREAD_INHERIT_SCHED ? "PTHREAD_INHERIT_SCHED" : "???");
          }
      
          {
              struct sched_param param;
              pthread_attr_getschedparam(&attr, &param);
              printf("default: sched_param    = %d\n", param.sched_priority);
          }
      
          {
              int sched_policy = 0;
              pthread_attr_getschedpolicy(&attr, &sched_policy);
              printf("default: sched policy   = %s\n",
                     sched_policy == SCHED_FIFO ? "SCHED_FIFO" :
                     sched_policy == SCHED_RR  ? "SCHED_RR" :
                     sched_policy == SCHED_OTHER ? "SCHED_OTHER" : "???");
          }
      
          {
              int scope = 0;
              pthread_attr_getscope(&attr, &scope);
              printf("default: scope          = %s\n",
                     scope == PTHREAD_SCOPE_SYSTEM ? "PTHREAD_SCOPE_SYSTEM" :
                     scope == PTHREAD_SCOPE_PROCESS ? "PTHREAD_SCOPE_PROCESS" : "???");
          }
      
          {
              void *stack_addr = NULL;
              size_t stack_size = 0;
              pthread_attr_getstack(&attr, &stack_addr, &stack_size);
              printf("default: stack_addr     = %p\n", stack_addr);
              printf("default: stack_size     = %lu\n", stack_size);
          }
      
          {
              void *stack_addr = NULL;
              pthread_attr_getstackaddr(&attr, &stack_addr); // 已弃用
              printf("default: stack_addr     = %p\n", stack_addr);
          }
      
          {
              size_t stack_size = 0;
              pthread_attr_getstacksize(&attr, &stack_size);
              printf("default: stack_size     = %lu\n", stack_size);
          }
          pthread_attr_destroy(&attr);
          exit(EXIT_SUCCESS);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
    • 输出

      default: detech state = PTHREAD_CREATE_JOINABLE
      default: guard size = 4096
      default: inherit sched = PTHREAD_INHERIT_SCHED
      default: sched_param = 0
      default: sched policy = SCHED_OTHER
      default: scope = PTHREAD_SCOPE_SYSTEM
      default: stack_addr = (nil)
      default: stack_size = 0
      default: stack_addr = (nil)
      default: stack_size = 8388608

    12. CMakeLists.txt

    cmake_minimum_required(VERSION 3.0.0)
    project(pthread_examples VERSION 0.1.0 LANGUAGES C)
    
    IF (CMAKE_BUILD_TYPE AND (CMAKE_BUILD_TYPE STREQUAL Debug))
        ADD_COMPILE_DEFINITIONS(DEBUG)
    ENDIF()
    
    # FindThreads Module
    # 该模块用于确定系统的线程库。
    # 如果查找到线程库,该模块定义目标:Threads::Threads
    # 定义以下变量:
    #   Threads_FOUND
    #       如果有支持的线程库被查找到
    #   CMAKE_THREAD_LIBS_INIT
    #       将要使用的线程库。如果该线程库是由系统库提供的,并且不需要特殊标志来使用它们,则可能为空
    #   CMAKE_USE_WIN32_THREADS_INIT
    #       如果查找到的库是WIN32,则返回1,否则返回0
    #   CMAKE_USE_PTHREADS_INIT
    #       指示找到的库是否为pthread兼容库
    #   CMAKE_HP_PTHREADS_INIT
    #       指示找到的库是否是HP线程库
    SET(THREADS_PREFER_PTHREAD_FLAG ON)
    find_package(Threads REQUIRED)
    IF (Threads_FOUND)
        message(STATUS ======================================================)
        message(STATUS "CMAKE_THREAD_LIBS_INIT       : ${CMAKE_THREAD_LIBS_INIT}")
        message(STATUS "CMAKE_USE_WIN32_THREADS_INIT : ${CMAKE_USE_WIN32_THREADS_INIT}")
        message(STATUS "CMAKE_USE_PTHREADS_INIT      : ${CMAKE_USE_PTHREADS_INIT}")
        message(STATUS "CMAKE_HP_PTHREADS_INIT       : ${CMAKE_HP_PTHREADS_INIT}")
        message(STATUS ======================================================)
        add_definitions     ( ${EIGEN3_DEFINITIONS} )
        include_directories ( ${EIGEN3_INCLUDE_DIRS} )
    ENDIF()
    
    # 链接线程库
    link_libraries(Threads::Threads)
    
    # 创建线程
    add_executable(pthread_create main.c)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
  • 相关阅读:
    【测控电路】信号分离电路 二阶滤波器 RC滤波电路
    Visual Studio Code 快捷键大全
    语义检索系统【全】:基于Milvus+ERNIE+SimCSE+IBN实现学术文献语义检索系统完整版
    Java面试题以及答案--SpringBoot
    Dynamic Potential-Based Reward Shaping将势能塑形奖励函数拓展为F(s,t,s‘,t‘)
    电脑换cpu要重装系统吗
    1-10嵌入式Linux系统开发与应用|嵌入式Linux|第三章 Linux编程环境
    【ARM Coresight Debug 系列 17 -- ARM Debug Vector Catch 详细介绍】
    Java FileOutputStream类简介说明
    明明加了唯一索引,为什么还是产生了重复数据?
  • 原文地址:https://blog.csdn.net/zhy29563/article/details/126669825