取消线程后如何杀死用pthread_create创建的所有子进程?

时间:2012-11-08 13:51:51

标签: c linux pthreads

我有以下代码,并且在 myprogram (我构建的应用程序的名称)的main()代码的每一步中都生成ps aux | grep myprogram

myprogram 的执行开始时,ps aux | grep myprogram只显示列表中 myprogram 的一次

取消我在main()的乞讨中创建的主题后,ps aux | grep myprogram显示 myprogram 两次,我希望只获得1。

有人可以解释这种行为吗?以及如何返回初始状态(仅1个myprogram)

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

pthread_t test_thread;

void *thread_test_run (void *v)
{
    int i=1;
    while(1)
    {
       printf("into thread %d\r\n",i);
       i++; 
       sleep(1);
    }
    return NULL
}

int main()
{
    // ps aux | grep myprogram  ---> show only 1 myprogram

    pthread_create(&test_thread, NULL, &thread_test_run, NULL);

    // ps aux | grep myprogram  ---> show  3 myprogram

    sleep (20);  


    pthread_cancel(test_thread);

    // ps aux | grep myprogram  ---> show 2 myprogram and I expected only 1 !!??

   // other function are called here...

    return 0;
}

修改

linux使用的libc是libc-0.9.30.1.so

# ls -l /lib/| grep libc
-rwxr-xr-x    1 root     root        16390 Jul 11 14:04 ld-uClibc-0.9.30.1.so
lrwxrwxrwx    1 root     root           21 Jul 30 10:16 ld-uClibc.so.0 -> ld-uClibc-0.9.30.1.so
lrwxrwxrwx    1 root     root           21 Jul 30 10:16 libc.so.0 -> libuClibc-0.9.30.1.so
-rw-r--r--    1 root     root         8218 Jul 11 14:04 libcrypt-0.9.30.1.so
lrwxrwxrwx    1 root     root           20 Jul 30 10:16 libcrypt.so.0 -> libcrypt-0.9.30.1.so
-rw-r--r--    1 root     root       291983 Jul 11 14:04 libuClibc-0.9.30.1.so

3 个答案:

答案 0 :(得分:3)

我假设你有一些过时的glibc(版本2.2或2.3),它使用了pthread的“linuxthreads”实现。

在这个较旧的库中,库创建了一个额外的线程用于线程管理;它可以在第一次调用pthread_create后创建;但是大部分时间都会睡觉。

在较新的linux中,存在带有NPTL(“Native posix线程库”)实现的glibc。使用它时,您将看不到ps axu中的线程;使用ps axum(使用m)查看本机线程。 NPTL不使用管理线程。

PS检查http://pauillac.inria.fr/~xleroy/linuxthreads/faq.html D.5回答:

  

D.5:当我运行一个创建N个线程的程序时,top或ps显示正在运行我程序的N + 2个进程。所有这些过程对应的是什么?

     

由于通用的“每个线程一个进程”模型,初始线程有一个进程,而使用pthread_create创建的线程有N个进程。这使得一个过程下落不明。这个额外的进程对应于“线程管理器”线程,一个由LinuxThreads内部创建的线程来处理线程创建和线程终止。这个额外的线程大部分时间都处于睡眠状态。

PPS:谢谢,Mohamed KALLEL;谢谢,mux:libc-0.9.30.1是uClibc,似乎它使用了相同的过时的linuxthreads实现(已知它不完全与posix兼容)。这是更改日志:http://web.archive.org/web/20070609171609/http://www.uclibc.org/downloads/Changelog

  

0.9.10 2002年3月21日

     

主要新功能:       o pthreads支持(源自glibc 2.1.3的linuxthreads库)           作者:Stefan Soucek和Erik Andersen

答案 1 :(得分:0)

可以是其他答案所建议的 pthreads实现,但是,如果您使用的是使用 NPTL 的glibc 2.4或更高版本,那么请注意,您使用的ps命令甚至不显示线程,而是使用:

ps -AL

pthread_cancel()之前和之后的输出是:

$ ps -AL | grep tst
  983   983 pts/2    00:00:00 tst
  983   984 pts/2    00:00:00 tst
$ ps -AL | grep tst
  983   983 pts/2    00:00:00 tst

有关uclibc的更多信息,特别是关于ps aux,因为它没有NPTL,然后{{1}}应该显示所有线程。

  

引入原生POSIX线程库(NPTL)   线程变得相当难以捉摸。 他们没有出现在   使用ps命令的默认进程列表如果你有   在目标上使用完整ps命令(来自procps包)的奢侈品   系统然后您需要做的就是添加“-L”选项。

答案 2 :(得分:0)

你有一个(非常)旧的linux系统,你的线程被ps等工具显示为进程,这在新的linux系统上不会发生

但是,线程通常在返回时不会被处置掉,或者你杀死/取消它。

要实现这一点,您必须在线程中调用pthread_detach(pthread_self())或以分离状态创建线程: 当该线程结束时,一个分离的线程将处置它的线程资源,稍后不能通过pthread_join()连接一个分离的线程。

pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, 1);
pthread_create(&test_thread, &attr, &thread_test_run, NULL);

或者您必须在其上调用pthread_join(),例如

pthread_create(&test_thread, NULL, &thread_test_run, NULL);

sleep (20);  
pthread_cancel(test_thread);
pthread_join(test_thread);

pthread_join()将确保释放线程资源。

这个概念大致类似于僵尸进程,在父进程调用wait()或类似进程之前,进程不会被处理掉。