线程
众所周知,进程是资源管理的最小单位,线程是程序执行的最小单位;一个进程下可以有多个线程,线程可以创建线程
pthread_create()
是用于创建一个线程的,创建线程实际上就是确定调用该线程函数的入口点,在线程创建后,就开始运行相关的线程函数
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
• thread:指向线程标识符的指针。
• attr:设置线程属性,具体内容在下一小节讲解。
• start_routine:start_routine 是一个函数指针,指向要运行的线程入口,即线程运行时要执行的函数代码。
• arg:运行线程时传入的参数。
• 返回值:若线程创建成功,则返回 0。若线程创建失败,则返回对应的错误代码。
typedef struct
{
int etachstate; //线程的分离状态
int schedpolicy; //线程调度策略
structsched_param schedparam; //线程的调度参数
int inheritsched; //线程的继承性
int scope; //线程的作用域
size_t guardsize; //线程栈末尾的警戒缓冲区大小
int stackaddr_set; //线程的栈设置
void* stackaddr; //线程栈的位置
size_t stacksize; //线程栈的大小
}pthread_attr_t;
pthread_attr_init()
初始化线程对象的属性,函数原型:
int pthread_attr_init(pthread_attr_t *attr);
• attr:指向一个线程属性的指针
• 返回值:若函数调用成功返回 0,否则返回对应的错误代码。
线程的分离状态
在任何一个时间点上,线程是可结合的(joinable),或者是分离的(detached)。一个可结合的线程能够被其他线程收回其资源和杀死
一个分离的线程是不能被其他线程回收或杀死的,它的存储器资源在它终止时由系统自动释放。
进程中的线程可以调用 pthread_join() 函数来等待某个线程的终止,获得该线程的终止状态,并收回所占的资源
int pthread_join(pthread_t tid, void **rval_ptr);
pthread_detach() 函数将此线程设置为分离状态,设置为分离状态的
线程在线程结束时,操作系统会自动收回它所占的资源
int pthread_detach(pthread_t tid);
如果一个线程是可结合的,意味着这条线程在退出时不会自动释放自身资源,而会成为僵尸线程,同时意味着该线程的退出值可以被其他线程获取。
如果在创建线程时就知道不需要了解线程的终止状态,那么可以通过修改 pthread_attr_t 结构中
的 detachstate 属性,让线程以分离状态启动
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
获取线程的分离状态:
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
• attr:指向一个线程属性的指针。
• detachstate:如果值为 PTHREAD_CREATE_DETACHED,则表示线程是分离状态,如果值为 PTHREAD_CREATE_JOINABLE 则表示线程是结合状态。
线程调度的策略
• 分时调度策略,SCHED_OTHER。这是线程属性的默认值,另外两种调度方式只能用于以超级用户权限运行的进程,因为它们都具备实时调度的功能,但在行为上略有区别。
• 实时调度策略,先进先出方式调度 (SCHED_FIFO)。基于队列的调度程序,对于每个优先级都会使用不同的队列,先进入队列的线程能优先得到运行,线程会一直占用 CPU,直到有更高优先级任务到达或自己主动放弃 CPU 使用权。
• 实时调度策略,时间片轮转方式调度 (SCHED_RR)。与 FIFO 相似,不同的是前者的每个线程都有一个执行时间配额,当采用 SHCED_RR 策略的线程的时间片用完,系统将重新分配时间片,并将该线程置于就绪队列尾,并且切换线程,放在队列尾保证了所有具有相同优先级的 RR 线程的调度公平。
int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched);
int pthread_attr_getinheritsched(const pthread_attr_t *attr, int*inheritsched);
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);
线程的优先级
int pthread_attr_setschedparam(pthread_attr_t *attr, const struct schedparam *param);
int pthread_attr_getschedparam(const pthread_attr_t *attr, struct schedparam *param);
线程栈
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize);
线程退出
void pthread_exit(void *retval);
例子:
int main()
{
debug_zlog_init();
pthread_t thread[2];
// system("echo 0 > /sys/class/leds/firefly:red:power/brightness");
// system("echo 0 > /sys/class/leds/firefly:green:user/brightness");
if (pthread_create(&thread[0], NULL, key_tick, NULL) != 0)
{
}
if (pthread_create(&thread[1], NULL, led, NULL) != 0)
{
}
pthread_join(thread[0], NULL);
pthread_join(thread[1], NULL);
return 0;
}
例子中的key_tick是一个按键的检测,led是一个切换led灯的颜色的函数,这两个互相不干涉,但是其实在实际的过程中,是会进行相互干涉的。