linux下pthread基本操作

常用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]$

猜你喜欢

转载自blog.csdn.net/zyj_zhouyongjun183/article/details/80150991