Linux线程管理

Linux线程管理(POSIX线程库)

一、创建线程
int pthread_create (pthread_t* restrict thread,
                    const pthread_attr_t* restrict attr,
                    void* (*start_routine) (void*),
                    void* restrict arg);

thread        - 线程ID,输出型参数。pthread_tunsigned long int
attr          - 线程属性,NULL表示缺省属性,如果没有特殊需求,一般写NULL即可
start_routine - 线程入口函数指针,参数和返回值的类型都是void*
				(启动线程本质上就是调用一个函数,只不过是在一个独立的线程中调用的,函数返回即线程结束)
arg           - 传递给线程过程函数的参数
返回值:成功返回0,失败返回错误码,但不会修改全局的错误变量,也就是无法使用perror获取错误原因。    
二、线程回收
int pthread_join (pthread_t thread, void** retval);
功能:等待thread参数所标识的线程结束,并回收相关资源,如果thread线程没有结束则<阻塞>
retval:获得线程正常结束时的返回值,是输出型的参数,用于获取线程入口函数的返回值。
返回值:成功返回0,失败返回错误码
    
从线程过程函数中返回值的方法:
	1、线程过程函数将所需返回的内容放在一块内存中,返回该内存的地址,保证这块内存在函数返回,即线程结束以后依然有效;
	2、若retval参数非NULL,则pthread_join函数将线程入口函数所返回的指针,拷贝到该参数所指向的内存中;
	3、线程入口函数所返回的指针指向text、data、bss内存段的数据,如果指向heap内存段,则还需保证在用过该内存之后释放之。
三、主、子线程
pthread_t pthread_self (void);
成功返回调用线程的ID,不会失败。
//pthread_self 返回的是相对于该进程内线程之间的ID,不同进程内可能重复,单个进程内唯一[POSIX]
//gettid返回的是内核中线程ID
int pthread_equal (pthread_t t1, pthread_t t2);
功能:若参数t1和t2所标识的线程ID相等,则返回非零,否则返回0。

注意:某些实现的pthread_t不是unsigned long int类型,可能是结构体类型,无法通过“==”判断其相等性。

四、终止线程

方法1:从线程入口函数中return,主线程除外。

方法2:调用pthread_exit函数。

void pthread_exit (void* retval);
retval - 和线程过程函数的返回值语义相同。

注意:在任何线程中调用exit函数都将终止整个进程。

主线程结束子线程是否会跟着一起结束?

不会,从表面看,当子线程还在执行而主线程执行到main函数最后一行代码,主线程就会执行main函数中显式或隐式(没写return编译器编译时会自动补上)的return语句,在main函数中执行return语句,就相当于执行exit函数,会导致整个进程一起结束(线程也就全部结束)。可以调用pthread_exit(NULL)让主线程先结束而不是让主线程掉用return结束整个进程,这样子线程就可以继续执行。

五、线程分离

同步方式(非分离状态):创建线程之后主线程调用pthread_join函数等待其终止,并释放线程资源。

异步方式(分离状态):无需创建者等待,线程终止后自行释放资源。

int pthread_detach (pthread_t thread);
功能:使thread参数所标识的线程进入分离(DETACHED)状态。
返回值:成功返回0,失败返回错误码。
//如果一个子线程需要长时间执行,不能正常结束,为了避免他的父线程陷入无尽的等待,可提前给子线程设置分离状态。
六、取消线程
1、向发送取消请求:
int pthread_cancel (pthread_t thread);
功能:该函数只是向线程发出取消请求,并不等待线程终止。

缺省情况下,线程在收到取消请求以后,并不会立即终止,而是仍继续运行,直到其达到某个取消点。
在取消点处,线程检查其自身是否已被取消了,并做出相应动作。
2、设置可取消状态:
int pthread_setcancelstate (int state,int* oldstate);
成功返回0,并通过oldstate参数输出原可取消状态(若非NULL),失败返回错误码。

state取值:
   PTHREAD_CANCEL_ENABLE  - 接受取消请求(缺省)。
   PTHREAD_CANCEL_DISABLE - 忽略取消请求。
3、设置可取消类型:
int pthread_setcanceltype (int type, int* oldtype);
成功返回0,并通过oldtype参数输出原可取消类型(若非NULL),失败返回错误码。

type取值:
   PTHREAD_CANCEL_DEFERRED     - 延迟取消(缺省)。
   被取消线程在接收到取消请求之后并不立即响应,而是一直等到执行了特定的函数(取消点)之后再响应该请求。
   PTHREAD_CANCEL_ASYNCHRONOUS - 异步取消。
   被取消线程可以在任意时间取消,不是非得遇到取消点才能被取消。
七、线程属性
int pthread_create (pthread_t* restrict thread,
                    const pthread_attr_t* restrict attr,
                    void* (*start_routine) (void*),
                    void* restrict arg);
//创建线程函数的第二个参数即为线程属性,传空指针表示使用缺省属性。

typedef struct {
    // 分离状态
    int detachstate;
       // PTHREAD_CREATE_DETACHED - 分离线程。
       // PTHREAD_CREATE_JOINABLE(缺省) - 可汇合线程。

    // 竞争范围
    int scope;
       // PTHREAD_SCOPE_SYSTEM - 在系统范围内竞争资源。
       // PTHREAD_SCOPE_PROCESS(Linux不支持) - 在进程范围内竞争资源。
    

    // 继承特性
    int inheritsched;
       // PTHREAD_INHERIT_SCHED(缺省) - 调度属性自创建者线程继承。
       // PTHREAD_EXPLICIT_SCHED - 调度属性由后面两个成员确定。
    

    // 调度策略
    nt schedpolicy;
        /* SCHED_FIFO - 先进先出策略。
             没有时间片。
             一个FIFO线程会持续运行,直到阻塞或有高优先级线程就绪。
             当FIFO线程阻塞时,系统将其移出就绪队列,待其恢复时再加到同优先级就绪队列的末尾。
             当FIFO线程被高优先级线程抢占时,它在就绪队列中的位置不变。
             因此一旦高优先级线程终止或阻塞,被抢占的FIFO线程将会立即继续运行。
            SCHED_RR - 轮转策略。
             给每个RR线程分配一个时间片,一但RR线程的时间片耗尽,系统即将移到就绪队列的末尾。
             SCHED_OTHER(缺省) - 普通策略。
             静态优先级为0。任何就绪的FIFO线程或RR线程,都会抢占此类线程。    
		*/
    // 调度参数
    struct sched_param schedparam;
        // struct sched_param {
        //     int sched_priority; /* 静态优先级 */
        // };
    

    // 栈尾警戒区大小(字节)  缺省一页(4096字节)。
    size_t guardsize;

    // 栈地址
    void* stackaddr;

    // 栈大小(字节)
    size_t stacksize;
} pthread_attr_t;

不要手动读写该结构体,而应调用pthread_attr_set/get函数设置/获取具体属性项。
1、设置线程属性:
初始化线程属性结构体:
pthread_attr_t attr = {}; // 不要使用这种方式
int pthread_attr_init (pthread_attr_t* attr);
设置具体线程属性项:
int pthread_attr_setdetachstate (pthread_attr_t* attr,int detachstate);
int pthread_attr_setscope (pthread_attr_t* attr,int scope);
int pthread_attr_setinheritsched (pthread_attr_t* attr,int inheritsched);
int pthread_attr_setschedpolicy (pthread_attr_t* attr,int policy);
int pthread_attr_setschedparam (pthread_attr_t* attr,const struct sched_param* param);
int pthread_attr_setguardsize (pthread_attr_t* attr,size_t guardsize);
int pthread_attr_setstackaddr (pthread_attr_t* attr,void* stackaddr);
int pthread_attr_setstacksize (pthread_attr_t* attr,size_t stacksize);
int pthread_attr_setstack (pthread_attr_t* attr,void* stackaddr, size_t stacksize);
以设置好的线程属性结构体为参数创建线程:
int pthread_create (pthread_t* restrict thread,
                    const pthread_attr_t* testrict attr,
                    void* (*start_routine) (void*),
                    void* restrict arg);
销毁线程属性结构体:
int pthread_attr_destroy (pthread_attr_t* attr);
2、获取线程属性:
获取线程属性结构体:
int pthread_getattr_np (pthread_t thread,pthread_attr_t* attr);
获取具体线程属性项:
int pthread_attr_getdetachstate (pthread_attr_t* attr,int* detachstate);
int pthread_attr_getscope (pthread_attr_t* attr,int* scope);
int pthread_attr_getinheritsched (pthread_attr_t* attr,int* inheritsched);
int pthread_attr_getschedpolicy (pthread_attr_t* attr,int* policy);
int pthread_attr_getschedparam (pthread_attr_t* attr,struct sched_param* param);
int pthread_attr_getguardsize (pthread_attr_t* attr,size_t* guardsize);
int pthread_attr_getstackaddr (pthread_attr_t* attr,void** stackaddr);
int pthread_attr_getstacksize (pthread_attr_t* attr,size_t* stacksize);
int pthread_attr_getstack (pthread_attr_t* attr,void** stackaddr, size_t* stacksize);
以上所有函数成功返回0,失败返回错误码。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值