AIX 6.1上的僵尸线程
我在AIX 6.1上遇到问题,一旦创建线程,它看起来不会死。AIX 6.1上的僵尸线程
编译: GCC -pthread sample.c文件 cc_r sample.c文件
两者有相同的结果。
我试图用三种方法分离线程。
1)主方法创建后调用pthread_detach。 2)Main方法尝试创建通过attr arg分离的线程。 3)线程函数调用pthread_detach。
我试图跟踪线程开始/停止导致所有线程完成。
所有三个按照这一呼吁在状态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);
}
我引用描述并行线程的文章实现对AIX:
内核维护一个列表,称为deathrow,LWP和柯rnel线程已退出,以便在需要创建新的(fork())时收获终止的LWP/kthread。如果一个LWP/kthread在僵尸列表中可用,内核不需要为新的k线程分配数据结构和堆栈;它仅使用僵尸kthread中的结构和堆栈,并将kthread链接到发出fork(2)(或thread_create())命令的进程。
在进程创建流程中,当forklwp()代码调用lwp_create()时,lwp_create()首先在deathrow上查找僵尸线程。如果存在,则LWP,kthread和堆栈会与进程关联,并且内核不必在fork()过程中分配新k线程,LWP和堆栈空间。内核简单地从死亡列表中获取结构,适当地链接指针,然后继续前进。从lwp_create()调用的thread_create()(内核线程创建,而不是用户线程API)传递LWP数据和堆栈,从而避免执行任何内核内存分配。
全部文章是在这里: http://flylib.com/books/en/2.830.1.30/1/