AIX 6.1上的僵尸线程

时间:2014-10-07 20:42:49

标签: pthreads

我在AIX 6.1上遇到问题,一旦创建了一个线程,它似乎不会消亡。

编译:    gcc -pthread sample.c    cc_r sample.c

两者都有相同的结果。

我试图以三种方式分离线索    1)主方法在创建后调用pthread_detach。    2)主方法尝试通过attr arg创建分离的线程。    3)调用pthread_detach的线程函数。

我尝试跟踪线程启动/停止导致所有线程完成。

根据此调用,ALl三个在状态Z中有许多线程

-bash-4.2# ps -mo THREAD -p `ps -ef | grep a.out | awk '{print $2}'` 
    USER    PID   PPID      TID ST  CP PRI SC    WCHAN        F     TT BND COMMAND 
    root 340028 278750        - A    0  60 11 f100010019c574b0   200001  pts/0   - ./a.out 10 3 
       -      -      -   450679 Z    0  60  1        -   c00001      -   - - 
       -      -      -   561215 Z    0  60  1        -   c00001      -   - - 
       -      -      -   573523 Z    0  60  1        -   c00001      -   - - 
       -      -      -   663653 Z    0  60  1        -   c00001      -   - - 
       -      -      -   684203 Z    0  60  1        -   c00001      -   - - 
       -      -      -   745711 Z    0  60  1        -   c00001      -   - - 
       -      -      -   753695 Z    0  60  1        -   c00001      -   - - 
       -      -      -   987139 Z    0  60  1        -   c00001      -   - - 
       -      -      -  1007867 Z    0  60  1        -   c00001      -   - - 
       -      -      -  1523761 S    0  60  1 f100010019c574b0   410400      -   - - 
       -      -      -  1536067 Z    0  60  1        -   c00001      -   - - 

这是代码(我知道它的草率!请原谅!)

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <ctype.h> 
#include <unistd.h> 
#include <pthread.h> 
#include <limits.h> 

#define DETACH_NONE                                                0 
#define DETACH_METHOD_DETACH_IN_MAIN         1 
#define DETACH_AT_PTHREAD_CREATE                2 
#define DETACH_IN_THREAD_FUNC                        3 
int g_nDetachMethod = DETACH_METHOD_DETACH_IN_MAIN; 

void increment_count(); 
void decrement_count(); 
long long get_count(); 
void set_count( long long c ); 
void *PrintHello2( void* ptr ); 
void displayThreadStatus( pthread_t tid ); 
void displayTopOutput(); 

void *PrintHello2( void* ptr ) 
{ 
        int rc; 
        pthread_t tid = pthread_self(); 
        sched_yield(); 
        increment_count(); 
                sleep( rand() % 10 + 1 ); 
                displayThreadStatus( tid ); 
                if( g_nDetachMethod == DETACH_IN_THREAD_FUNC ) 
                { 
                        rc = pthread_detach( tid ); 
                        printf("\t\tDetach result: %d.\n", rc); 
                        displayThreadStatus( tid ); 
                } 
        decrement_count(); 
        pthread_exit (NULL); 
} 

int main( int argc, char *argv[] ) 
{ 
        pthread_t thds; 
        int i, count, num_threads, rc; 

        set_count( 0 ); 

        if( argc < 2 ) 
        { 
                printf("Specify on the command line which detach method to use and the number of threads.\n"); 
                printf("Usage: %s threads detachmethod\n", argv[0]); 
                printf("\t     threads: The count of child threads to spawn.  Default=10\n"); 
                printf("\tdetachmethod: The point at which detach should be called.  Default=%d\n", DETACH_METHOD_DETACH_IN_MAIN); 
                printf("\t\t\t%d: Do not attempt to detach.  Default behaviour is joinable.\n"); 
                printf("\t\t\t%d: Call pthread_detach right after pthread_create in main.\n", DETACH_METHOD_DETACH_IN_MAIN); 
                printf("\t\t\t%d: Call pthread_create with pthread_attr_setdetachstate attribute set to PTHREAD_CREATE_DETACHED.\n", DETACH_AT_PTHREAD_CREATE); 
                printf("\t\t\t%d: Call pthread_detach inside the thread function.\n", DETACH_IN_THREAD_FUNC); 
                printf("\nExample:\n"); 
                printf("\t a.out 10 %d\n", DETACH_METHOD_DETACH_IN_MAIN); 
                exit(0); 
        } 

        printf("Using Threads:\"%s\" Detach method:\"%s\"\n", argv[1], argv[2]); 

        num_threads = atoi( argv[1] ); 
        g_nDetachMethod = atoi( argv[2] ); 

        printf("\n\n=======  CREATING %d THREADS =======\n", num_threads); 
        for( i = 0; i < num_threads; i++ ) 
        { 
                printf( "\n\tcreating thread : %d \n", i ); 
                if( g_nDetachMethod == DETACH_AT_PTHREAD_CREATE ) 
                { 
                        pthread_attr_t tattr; 
                        pthread_attr_init(&tattr); 
                        pthread_attr_setdetachstate(&tattr,PTHREAD_CREATE_DETACHED); 
                        pthread_create( &thds, &tattr, PrintHello2, (void*) NULL ); 
                } 
                else 
                { 
                        pthread_create( &thds, NULL, PrintHello2, (void*) NULL ); 
                        if( g_nDetachMethod == DETACH_METHOD_DETACH_IN_MAIN ) 
                        { 
                                rc = pthread_detach( thds ); 
                                printf("\t\tDetach result: %d.\n", rc); 
                        } 
                } 
        } 

        printf("\n\n=======  WAITING FOR THREADS TO FINISH =======\n"); 
        for( i = 0; i < 20; i++ ) 
        { 
                sleep( 1 ); 
                count = get_count(); 
                printf( "\tLoop: %d, Active Threads: %d, Sleep seconds: %d\n", i, count, (i + 1) ); 
                if( count == 0 ) 
                        break; 
        } 

        displayTopOutput(); 
        printf("\n\n=======  WAITING FOR 10 SECONDS TO MANUALLY QUERY FOR DEFUNCT PROCESSES =======\n"); 
        printf("ps -mo THREAD -p `ps -ef | grep a.out | awk '{print $2}'`\n"); 
        for( i = 10; i >= 0; i-- ) 
        { 
                sleep( 1 ); 
                printf( "\r%d seconds remaining.", i ); 
                fflush (stdout); 
        } 

        count = get_count(); 
        printf("\n\n=======  FINAL STATUS Active Threads: %d =======\n", count ); 
        displayTopOutput(); 
        return 0; 
} 

void displayThreadStatus( pthread_t tid ) 
{ 
/*        int state; 
        pthread_attr_t attr; 

        pthread_getattr_np( pthread_self(), &attr); 
        pthread_attr_getdetachstate( &attr, &state ); 
        printf("\t\t[%d]: %s\n", tid, state == PTHREAD_CREATE_DETACHED? "PTHREAD_CREATE_DETACHED": "PTHREAD_CREATE_JOINABLE"); 
        */ 
} 

void displayTopOutput() 
{ 
        if( fork() != 0 ) 
        { 
                int status; 
                wait( &status ); 
                return; 
        } 
        pid_t pid = getppid(); 
        char buffer[10]; 
        sprintf( buffer, "%d", (int) pid ); 
        printf( "PID: %s\n", buffer ); 
        /* execl( "/usr/bin/top", "top", "-H", "-b", "-n", "1", "-d", "1", "-p", buffer, (char *) NULL ); */ 
        execl("/usr/bin/ps", "ps", "-mo", "THREAD", "-p", buffer, (char *) NULL ); 
        printf("\n"); 
        exit( 0 ); 
} 

pthread_mutex_t count_mutex; 
long long count=0; 

void increment_count() 
{ 
        pthread_mutex_lock( &count_mutex ); 
        count = count + 1; 
        pthread_mutex_unlock( &count_mutex ); 
} 

void decrement_count() 
{ 
        pthread_mutex_lock( &count_mutex ); 
        count = count - 1; 
        pthread_mutex_unlock( &count_mutex ); 
} 

long long get_count() 
{ 
        long long c; 
        pthread_mutex_lock( &count_mutex ); 
        c = count; 
        pthread_mutex_unlock( &count_mutex ); 
        return (c); 
} 

void set_count( long long c ) 
{ 
        pthread_mutex_lock( &count_mutex ); 
        count = c; 
        pthread_mutex_unlock( &count_mutex ); 
} 

1 个答案:

答案 0 :(得分:0)

我引用了一篇描述AIX上pthreads实现的文章:

内核维护一个名为deathrow的列表,它已经退出LWP和内核线程,以便在需要创建新的LWP / kthread时获得终止的LWP / kthread(fork())。如果僵尸列表中有LWP / kthread,则内核不需要为新的kthread分配数据结构和堆栈;它只是使用zombie kthread中的结构和堆栈,并将kthread链接到发出fork(2)(或thread_create())命令的进程。

在进程创建流程中,当forklwp()代码调用lwp_create()时,lwp_create()首先在deathrow上查找僵尸线程。如果存在,则LWP,kthread和堆栈链接到进程,并且内核不需要在fork()进程期间分配新的kthread,LWP和堆栈空间。内核只是从deathrow列表中抓取结构,适当地链接指针,然后继续前进。从lwp_create()调用的thread_create()(内核线程创建,而不是用户线程API)传递LWP数据和堆栈,从而避免进行任何内核内存分配。

全文在这里: http://flylib.com/books/en/2.830.1.30/1/