我有以下代码,并且在 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
答案 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回答:
PPS:谢谢,Mohamed KALLEL;谢谢,mux:libc-0.9.30.1是uClibc,似乎它使用了相同的过时的linuxthreads实现(已知它不完全与posix兼容)。这是更改日志:http://web.archive.org/web/20070609171609/http://www.uclibc.org/downloads/ChangelogD.5:当我运行一个创建N个线程的程序时,top或ps显示正在运行我程序的N + 2个进程。所有这些过程对应的是什么?
由于通用的“每个线程一个进程”模型,初始线程有一个进程,而使用pthread_create创建的线程有N个进程。这使得一个过程下落不明。这个额外的进程对应于“线程管理器”线程,一个由LinuxThreads内部创建的线程来处理线程创建和线程终止。这个额外的线程大部分时间都处于睡眠状态。
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()或类似进程之前,进程不会被处理掉。