常用pthread函数
- int pthread_attr_init (pthread_attr_t *__attr), 初始化pthread创建参数;
- int pthread_attr_destroy (pthread_attr_t *__attr),销毁pthread创建参数;
- int pthread_attr_getdetachstate (const pthread_attr_t *__attr,int *__detachstate)获取线程参数中的分离状态;
- int pthread_attr_setdetachstate (pthread_attr_t *__attr, int __detachstate)设定线程的分离状态PTHREAD_CREATE_DETACHED或者PTHREAD_CREATE_JOINABLE;
- int pthread_attr_setinheritsched (pthread_attr_t *__attr, int __inherit)设定线程调度策略的继承属性,该函数必须在root权限下调用;
- int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy),设定线程的调度策略;
- int pthread_attr_getschedparam (const pthread_attr_t *__restrict __attr, struct sched_param *__restrict __param),获取参数中的线程优先级;
- int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr, const struct sched_param *__restrict __param),设定线程的优先级;
- int pthread_create (pthread_t __restrict __newthread,const pthread_attr_t *__restrict __attr,void (__start_routine) (void ),void *__restrict __arg), 创建线程,其中__attr和__arg可用为NULL,使用默认参数创建线程,并且线程函数无输入参数;
- int pthread_join (pthread_t __th, void **__thread_return);等待线程退出后返回,获取线程的返回值,并且释放线程资源和线程ID号;__thread_return可以为NULL,不关心返回值;并且线程必须是非分离线程PTHREAD_CREATE_JOINABLE;
一个线程创建示例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <string>
#include <iostream>
using namespace std;
#define TRUE 1
#define FALSE 0
static void *_thread1(void* arg)
{
static unsigned count = 0;
//获取当前线程的ID;
pthread_t threadID = pthread_self();
while(1)
{
//线程在运行结束后显式调用pthread_exit()退出,并返回count;
//也可以直接break退出while(),然后return返回;
if(count>4)
{
printf("exit :%s\n", __FUNCTION__);
pthread_exit((void*)&count);
//break;
}
//打印线程创建时的输入的字符串;
printf("The thread ID is:0x%x, inputstr:%s\n", threadID, ((string*)arg)->c_str());
sleep(1);
count++;
}
return (void*)&count;
}
static void _threadAttrSet(pthread_attr_t *attr, unsigned priority, bool bDetached)
{
struct sched_param schParam;
//设定线程的继承性,如果需要认为设定线程的调度策略和优先级,必须将线程的继承策略设定为
//PTHREAD_EXPLICIT_SCHED;不然默认值为PTHREAD_INHERIT_SCHED,表示新线程继承创建线程调度策略和参数;
//该函数必须在root权限才能正常调用;
pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
//设定是否为分离线程PTHREAD_CREATE_DETACHED,如是,则线程在退出时自动回收资源和线程ID,并且无返回值;
//如是PTHREAD_CREATE_JOINABLE,则在线程退出后,需要调用pthread_join去显式回收线程资源,可用获取线程返回值;
if(bDetached)
pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED);
else
pthread_attr_setdetachstate(attr, PTHREAD_CREATE_JOINABLE);
//设定线程的调度策略,默认值为SCHED_OTHER,分时调度策略;
//可用显式设定为SCHED_FIFO和SCHED_RR;SHCED_RR是实时调度,但是当自己的时间片用完后,
//系统将重新分配时间片,放在就绪队列尾,保证其他RR线程也可以得到CPU运行;SCHED_FIFO是一旦占用到CPU后,
//就一直运行,直到有更高优先级的线程出现;
//并且不同调度策略下,可用的优先级范围可能不同,需要使用int sched_get_priority_max(int policy);
//和int sched_get_priority_min(int policy);获取不同策略下的可用优先级参数;
//RR和FIFO这两种调度策略,一定是需要root权限才能使用(或者使用linux的capability机制);
pthread_attr_setschedpolicy(attr, SCHED_RR);
//先从attr中获取优先级参数,然后再将user的优先级参数设定下去;
pthread_attr_getschedparam(attr, &schParam);
schParam.sched_priority = priority;
pthread_attr_setschedparam(attr, &schParam);
return;
}
int main(int argc, char *argv[])
{
pthread_t thread1ID;
pthread_attr_t thread1Attr;
static const string inputStr = "my name is zoobi!";
void *thread1Ret = NULL;
//初始化线程创建参数thread1Attr;
pthread_attr_init(&thread1Attr);
_threadAttrSet(&thread1Attr, 32, FALSE);
//创建线程,输入参数为对象inputStr的地址;
if(0 != pthread_create(&thread1ID, &thread1Attr, _thread1, (void*)&inputStr))
{
printf("pthread_create failed!\n");
return -1;
}
//等待线程ID为thread1ID的非分离线程退出,并获取线程的返回值thread1Ret;
//该函数成功应该返回0;如果返回 EDEADLK,表示线程内部右死锁;返回EINVAL,则线程是分离线程,
//分离线程不用调用pthread_join,系统会自动回收线程资源;返回EINVAL,重复调用pthread_join等待
//同一线程退出;返回ESRCH,则线程ID是非法的;
int ret = pthread_join(thread1ID, &thread1Ret);
if(0 != ret)
{
printf("pthread_join failed!, the ret:%d\n", ret);
}
else
{
printf("The task return value is:%d\n", *((unsigned*)thread1Ret));
}
//显式销毁线程创建参数thread1Attr,必须要重新做pthread_attr_init才能使用该参数;
pthread_attr_destroy(&thread1Attr);
while(1)
{
printf("main thread !\n");
sleep(50);
}
return 0;
}
上面demo需要在root权限下编译运行,如下:
[root@localhost linux_env]# g++ pthread_test.cpp -o pthread_test -lpthread
[root@localhost linux_env]# ./pthread_test
The thread ID is:0x2264c700, inputstr:my name is zoobi!
The thread ID is:0x2264c700, inputstr:my name is zoobi!
The thread ID is:0x2264c700, inputstr:my name is zoobi!
The thread ID is:0x2264c700, inputstr:my name is zoobi!
The thread ID is:0x2264c700, inputstr:my name is zoobi!
exit :_thread1
The task return value is:5
main thread !
^C
[root@localhost linux_env]#
中间有遇到一个小问题,用gcc编译cpp文件,有下面错误:
[zoobi@localhost linux_env]$ gcc pthread_test.cpp -o pthread_test -lpthread
/tmp/cckTCQRf.o:在函数‘_thread1(void*)’中:
pthread_test.cpp:(.text+0x46):对‘std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::c_str() const’未定义的引用
/tmp/cckTCQRf.o:在函数‘main’中:
pthread_test.cpp:(.text+0x135):对‘__cxa_guard_acquire’未定义的引用
pthread_test.cpp:(.text+0x14f):对‘std::allocator<char>::allocator()’未定义的引用
pthread_test.cpp:(.text+0x165):对‘std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)’未定义的引用
pthread_test.cpp:(.text+0x16f):对‘__cxa_guard_release’未定义的引用
pthread_test.cpp:(.text+0x17e):对‘std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()’未定义的引用
pthread_test.cpp:(.text+0x18f):对‘std::allocator<char>::~allocator()’未定义的引用
pthread_test.cpp:(.text+0x26a):对‘std::allocator<char>::~allocator()’未定义的引用
pthread_test.cpp:(.text+0x278):对‘__cxa_guard_abort’未定义的引用
/tmp/cckTCQRf.o:在函数‘__static_initialization_and_destruction_0(int, int)’中:
pthread_test.cpp:(.text+0x2b3):对‘std::ios_base::Init::Init()’未定义的引用
pthread_test.cpp:(.text+0x2c2):对‘std::ios_base::Init::~Init()’未定义的引用
/tmp/cckTCQRf.o:(.eh_frame+0x67):对‘__gxx_personality_v0’未定义的引用
collect2: 错误:ld 返回 1
原因是gcc默认编译链接是不会链接C++标准库的,可用使用g++编译链接,当然也可以使用gcc链接时显式指定链接-lstdc++:
gcc pthread_test.cpp -o pthread_test -lpthread -lstdc++
上面demo改到普通用户下运行,由于有调用pthread_attr_setinheritsched,所以导致创建线程失败,如下:
[zoobi@localhost linux_env]./pthread_test
pthread_create failed!
[zoobi@localhost linux_env]$