Basic operations of pthread under linux

Common pthread functions

  • int pthread_attr_init (pthread_attr_t *__attr), initialize pthread creation parameters;
  • int pthread_attr_destroy (pthread_attr_t *__attr), destroy pthread creation parameters;
  • int pthread_attr_getdetachstate (const pthread_attr_t *__attr, int *__detachstate) gets the detached state in the thread parameters;
  • int pthread_attr_setdetachstate (pthread_attr_t *__attr, int __detachstate) sets the thread's detachment state PTHREAD_CREATE_DETACHED or PTHREAD_CREATE_JOINABLE;
  • int pthread_attr_setinheritsched (pthread_attr_t *__attr, int __inherit) sets the inheritance attribute of the thread scheduling policy, this function must be called with root privileges;
  • int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy), set the thread scheduling policy;
  • int pthread_attr_getschedparam (const pthread_attr_t *__restrict __attr, struct sched_param *__restrict __param), get the thread priority in the parameter;
  • int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr, const struct sched_param *__restrict __param), set the priority of the thread;
  • int pthread_create (pthread_t __restrict __newthread,const pthread_attr_t *__restrict __attr,void ( __start_routine) (void ),void *__restrict __arg), create a thread, where __attr and __arg can be NULL, create a thread with default parameters, and the thread function has no Input parameters;
  • int pthread_join (pthread_t __th, void **__thread_return); wait for the thread to exit and return, get the return value of the thread, and release the thread resource and thread ID number; __thread_return can be NULL, do not care about the return value; and the thread must be a non-detached thread PTHREAD_CREATE_JOINABLE ;

A thread creation example

#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;
}

The above demo needs to be compiled and run under root privileges, as follows:

[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]#

I encountered a small problem in the middle. When I compiled the cpp file with gcc, I got the following error:

[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

The reason is that the default compilation link of gcc will not link the C++ standard library. You can use g++ to compile and link, of course, you can also use gcc to explicitly specify the link when linking -lstdc++:

gcc pthread_test.cpp -o pthread_test -lpthread -lstdc++

The above demo is changed to run under the ordinary user. Because pthread_attr_setinheritsched is called, the thread creation fails, as follows:

[zoobi@localhost linux_env]./pthread_test
pthread_create failed!
[zoobi@localhost linux_env]$

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325628621&siteId=291194637