目前分類:pthread (6)

瀏覽方式: 標題列表 簡短摘要

今天工作上遇到 pthread_create() 一直回覆 11 (EAGAIN) 的錯誤值,原來是 threads 開啟數量超過極限值(/proc/sys/kernel/threads-max),不知什麼原因。

  • 取得某 pid 的 threads 總數: ps -o nlwp [pid]
  • 取得系統 threads 總數: ps -eo nlwp | tail -n +2 | awk '{ num_threads += $1 } END { print num_threads }'
  • 利用程式取得 threads 總數,可經由查看 /proc/getpid()/status,其中 Threads 的數字。

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

當 thread 設定 PTHREAD_CREATE_DETACHED 屬性時,thread 執行結束時不會保留返回值,會直接釋放所有資源並結束。當使用 pthread_join 一個 PTHREAD_CREATE_DETACHED 屬性的執行緒,會返回錯誤值,而且也得不到返回值。

#include 
#include 
#include 

void* thread_func(void *param)
{
    int i=0;
    int *running = (int*)param;
    printf("[%s:%d,%s]thread start\n", __FILE__, __LINE__, __func__);
    while(*running) {
        printf("[%s:%d,%s]%d\n", __FILE__, __LINE__, __func__, i++);
        sleep(1);
    }
    printf("[%s:%d,%s]thread stop\n", __FILE__, __LINE__, __func__);
    return (void*)123;
}

int main(int argc, char **argv)
{
    void *return_value=0;
    int running;
    pthread_t thrid;
    pthread_attr_t attr;

    running = 1;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    pthread_create(&thrid, &attr, thread_func, (void*)&running);
    pthread_attr_destroy(&attr);
    sleep(5);
    running = 0;
    pthread_join(thrid, &return_value);
    printf("[%s:%d,%s]%d\n", __FILE__, __LINE__, __func__, (int)return_value);
    sleep(1);
    return 0;
}
# ./a.out
[test.cpp:9,thread_func]thread start
[test.cpp:11,thread_func]0
[test.cpp:11,thread_func]1
[test.cpp:11,thread_func]2
[test.cpp:11,thread_func]3
[test.cpp:11,thread_func]4
[test.cpp:32,main]0
[test.cpp:14,thread_func]thread stop

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

一般正常使用 pthread_create 的執行緒,在執行結束時會保留返回值等待 pthread_join 呼叫傳回,也就是說執行緒所使用的資源會等到 pthread_join 才會被釋放。

#include 
#include 
#include 

void* thread_func(void *param)
{
    int i=0;
    int *running = (int*)param;
    printf("[%s:%d,%s]thread start\n", __FILE__, __LINE__, __func__);
    while(*running) {
        printf("[%s:%d,%s]%d\n", __FILE__, __LINE__, __func__, i++);
        sleep(1);
    }
    printf("[%s:%d,%s]thread stop\n", __FILE__, __LINE__, __func__);
    return (void*)123;
}

int main(int argc, char **argv)
{
    void *return_value;
    int running;
    pthread_t thrid;

    running = 1;
    pthread_create(&thrid, NULL, thread_func, (void*)&running);
    sleep(5);
    running = 0;
    pthread_join(thrid, &return_value);
    printf("[%s:%d,%s]%d\n", __FILE__, __LINE__, __func__, (int)return_value);
    return 0;
}
# ./a.out
[test.cpp:9,thread_func]thread start
[test.cpp:11,thread_func]0
[test.cpp:11,thread_func]1
[test.cpp:11,thread_func]2
[test.cpp:11,thread_func]3
[test.cpp:11,thread_func]4
[test.cpp:14,thread_func]thread stop
[test.cpp:28,main]123

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

#include 
#include 
#include 

class testClass
{
public:
    testClass();
    ~testClass();
private:
    static void *thread_func(void*);
    pthread_t thrid;
};

testClass::testClass()
{
printf("[%s:%d,%s]\n", __FILE__, __LINE__, __func__);
    pthread_create(&thrid, NULL, thread_func, this);
}

testClass::~testClass()
{
printf("[%s:%d,%s]\n", __FILE__, __LINE__, __func__);
    pthread_cancel(thrid);
    pthread_join(thrid, NULL);
}

void* testClass::thread_func(void *param)
{
    int i=0;
    testClass *self = (testClass*)param;
printf("[%s:%d,%s]thread start\n", __FILE__, __LINE__, __func__);
    while(1) {
        printf("[%s:%d,%s]%d\n", __FILE__, __LINE__, __func__, i++);
        sleep(1);
    }
printf("[%s:%d,%s]thread stop\n", __FILE__, __LINE__, __func__);
    return (void*)0;
}

int main(int argc, char **argv)
{
    testClass *test;
    test = new testClass();
    sleep(10);
    delete test;
    return 0;
}
# ./a.out
[test.cpp:18,testClass]
[test.cpp:33,thread_func]thread start
[test.cpp:35,thread_func]0
[test.cpp:35,thread_func]1
[test.cpp:35,thread_func]2
[test.cpp:35,thread_func]3
[test.cpp:35,thread_func]4
[test.cpp:35,thread_func]5
[test.cpp:35,thread_func]6
[test.cpp:35,thread_func]7
[test.cpp:35,thread_func]8
[test.cpp:35,thread_func]9
[test.cpp:24,~testClass]

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

int pthread_setcancelstate(int state, int *oldstate);
  • 作用:設置可取消的狀態
  • PTHREAD_CANCEL_ENABLE: 線程取消請求將被傳遞。(預設值)
  • PTHREAD_CANCEL_DISABLE: 代表針對目標線程的取消請求將處於未决狀態(未決代表為不處理,但請求依然存在)。除非線程修改自己的狀態,否則不會被取消。
int pthread_setcanceltype(int state, int *oldstate);
  • 作用:設定線程接收到CANCEL信號的執行時間
  • PTHREAD_CANCEL_DEFFERED: 表示線程接收到CANCEL信號會執行到下一個取消點退出。(預設值)
  • PTHREAD_CANCEL_ASYCHRONOUS: 表示線程接收到CANCEL信號立即終止。
#include 
#include 
#include 

long long int count=0;

void *func(void *param)
{
//  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
    printf("thread begin...\n");
    while (1) count++;
    printf("thread end...\n");
}

int main(int argc, char *argv[])
{
    int i;
    pthread_t thrid;

    // start thread
    if (pthread_create(&thrid, NULL, func, NULL)) {
        printf("pthread_create error\n");
        return -1;
    }

    // sleep
    for (i=0; i<5; i++) {
        sleep(1);
        printf("count=%lld\n", count);
    }

    // pthread cancel test
    if (!pthread_cancel(thrid)) printf( "pthread_cancel OK\n" );
    for (i=0; i<5; i++) {
        sleep(1);
        printf("count=%lld\n", count);
    }

    return 0;
}
執行結果
# ./a.out
thread begin...
count=25852274
count=54434882
count=85712448
count=116924962
count=139751253
pthread_cancel OK
count=139751253
count=139751253
count=139751253
count=139751253
count=139751253

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

pthread_cancel 用來停止 thread 有限制,以下的程式碼根本停不了,因為有沒有 Cancellation-point。

線程取消的方法是向目標線程發送 CANCEL 信號,但如何處理 Cancel 信號則由目標線程自己決定,或者忽略、或者立即終止、或者繼續運行至 Cancellation-point(取消點),由不同的 Cancellation 狀態決定。

線程接收到 CANCEL 信號的預設處理(即pthread_create()建立線程的預設狀態)是繼續執行至取消點,也就是說設置一個 CANCELED 狀態,線程繼續執行,只有執行至 Cancellation-point 的時候才會退出。

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()