我在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 );
}
答案 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数据和堆栈,从而避免进行任何内核内存分配。