头文件:#include <pthread.h> b函数原型:int pthread_created(pthread_t *thread,pthread_attr_t *attr,void * (*start_routine)(void *),void *arg); 函数参数含义: thread:该参数是一个指针,当线程创建成功时,用来返回创建的线程的ID. attr:该参数用于指定线程的属性,NULL表示默认属性. start_routine:该参数为一个函数指针,指向线程创建后要调用的函数; arg:该参数指向传递给线程函数的参数. 线程创建成功时,pthread_create函数返回0,若不为0,则说明创建线程失败,常见的错误码为EAGAIN,和EINVAL,前者表示系统限制创建新的线程.后者表示第2参数代表的线程属性值非法,线程创建成功后,新创建的线程开始运行第3个参数所指的函数,原来的线程继续运行. pthread_create函数的第2个参数attr是一个指向pthread_attr_t结构体的指针,该结构体指明待创建的线程的属性.看个例子:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h> int *thread(void *arg) { pthread_t newthid; newthid=pthread_self(); printf("这是新的线程 ID = %u\n",(unsigned int)newthid); return NULL; } int main(void) { pthread_t thid; printf("主线程的ID is %u\n",(unsigned int)pthread_self()); //打印主线程ID; if(pthread_create(&thid,NULL,(void *)thread,NULL)!=0) { printf("线程创建失败!\n"); exit(1); } sleep(1); exit(0); }
结果:
yang@liu:~/syc/第八章$ ./createthread 主线程的ID is 2025752320 这是新的线程 ID = 2017445632
创建线程的其它系统函数:
pthread_t pthread_self(void) 获取本线程的线程 id; pthread_equal(pthread_t thread,pthread_t thread2) 判断两个线程id是否指向同一个线程. int pthread_once(pthread_once_t *once_control,void (*init_routinue)(void)) 用来保证init_routinue线程函数在进程中仅执行一次.看个例子:
#include <stdio.h> #include <stdlib.h> #include <pthread.h> pthread_once_t once=PTHREAD_ONCE_INIT; void run() { printf("我是功能函数,我正在运行,ID = %u\n",(unsigned)pthread_self()); } void *thread1() { pthread_t thid=pthread_self(); printf("当前的线程ID = %u\n",(unsigned)thid); pthread_once(&once,run); printf("thread1结束!\n"); } void *thread2() { pthread_t thid=pthread_self(); printf("当前的线程ID = %u\n",(unsigned)thid); pthread_once(&once,run); printf("thread2结束!\n"); } int main() { pthread_t thid1,thid2; pthread_create(&thid1,NULL,thread1,NULL); pthread_create(&thid2,NULL,thread2,NULL); sleep(3); printf("主线程结束!\n"); exit(0); }
结果:
yang@liu:~/syc/第八章$ ./createthread 当前的线程ID = 2849777408 我是功能函数,我正在运行,ID = 2849777408 thread2结束! 当前的线程ID = 2858170112 thread1结束! 主线程结束!
可以看出函数run在线程thread1中运行了一次后,线程thread2虽然也调用了run ,但未执行: 线程属性: 线程创建函数pthread_create有一个参数为pthread_attr_t.结构体定义如下: typedef struct { int detachstate; int schedpolicy; struct sched_param schedparam; int inheritsched; int scope; size_t guardsize; int stackaddr_set; void * stackaddr; size_t stacksize; }pthread_attr_t; 各个字段的意义如下: datachstate表示新创建的线程是否与进程中的其它线程脱离同步,datachstate的缺省值为PTHREAD_CREATE_JOINABLE状态,这个属性也可以用函数pthread_detach()来设置,如果将detachstate设置为PTHREAD_CREAT_DETACH状态;则detachstate 不能在恢复到PTHREAD_CREATE_JOINABLE状态; schedpolicy:表示新的线程的调度策略,主要包括 SCHED_OTHER(正常,非实时),SCHED_RR(实时,轮转法)和SCHED_FIFO(实时,先入先出)3种,缺省值为SCHED_OTHER,后两种调度策略仅对超级用户有效. schedparam:一个struct sched_param结构,其中有一个sched_priority整形变量表示线程的运行优先级,这个参数仅当调度策略为实,(即 SCHED_RR 或 SCHED_FIFO)时才有效缺省值为0. inheritsched:有两种值可供选择:PTHREAD_EXPLICIT_SCHED和PIHREAD_INHERIT_SCHED,前者表示定调新的线程显示指度策略和调度参数(即attr 中的值),而后者表示继承调用者线程的值,缺省的值为PTHREAD_EXPLICIT_SCHED. scope:表示线程竞争CPU的范围,也就是说,线程的优先级的有效范围,POSIX的标准中定义了两个值,PTHREAD_SCOPE_SYSTEM和PTHREAD_SCOPE_PROCESS,前者表示与系统中的所有线程一起竞争CPU,后者表示仅与同进程中的线程竞争CPU . guardsize;境界堆栈的大小, stackaddr_set:堆栈地址集; stacksddr:堆栈的地址; satcksize:堆栈的大小; lInux下提供了了一些函数来获取和设置这些状态的函数. posix标准指定了三种调度策略,先入先出策略(SCHED_FIFO,实时),循环策略(SCHED_RR实时)和自定义策略(SCHED_OTHER正常,非实时),SCHED_FIFO是基于队列的调度程序,对于每个优先级都会使用不同的队列,SCHED_RR和FIFO相似,不同的是前者的每个线程都有一个执行时间配额.SCHED_FIFO 和 SCHED_RR 是对 POSIX Realtime 的扩展。SCHED_OTHER 是缺省的调度策略。提供了两个调度范围:进程范围(PTHREAD_SCOPE_PROCESS)和系统范围(PTHREAD_SCOPE_SYSTEM).具有不同范围状态的线程可以在一个系统甚至同一个进程中共存.进程范围只允许这种线程与同一进程中的其它线程争用资源,而系统范围则允许此类线程与系统内的其它所有线程争用资源, SCHED_FIOF:允许一个线程一直运行直到有更高优先级的线程准备好或者自愿阻塞自己,在SCHED_FIFO调度策略下,当一个线程准备好时,除非有平等或更高优先级的线程在运行,否则很快开始运行. SCHED_RR:即轮询与SCHED_FIFO不同的地方是:在SCHED_RR调度策略下,当一个线程运行了一个固定的时间段(时间片与间隔)后还没有阻塞.这时候如果有相同的优先级(SCHED_FIFO)或者(SCHED_RR)线程准备好时.运行中的线程将被抢占以使准备好的同优先级的线程得以运行的机会. 2,使用pthread_attr_getschedpolicy(pthread_attr_t *attr,int *policy)得到线程调度策略;使用pthread_attr_setschedpolicy(pthread_attr_t *attr,int policy)设置线程posix指定的3中策略属性:SCHED_FIFO,SCHED_RR,SCHED_OTHER.