前天看书,看到有一道题,就是说父线程如果因故退出,那么子线程还能存在么?
本来以为这问题很简单,答案是 不能存在
可这两天看了几篇文章后,觉得答案不是这么直白
在willimstallings的Operating Systems, Fourth Edition里,
(http://williamstallings.com/OS4e.html 有书的有关资料)
他把线程分为了两种,用户级线程(user level thread,ULT),内核级线程(kernel level thread,KLT)
对于用户级线程,内核没有关于线程的概念,只有进程,因此,所有的父子进程都会在同一时刻退出。
但对于KLT,就不是那么简单了
昨天忽然在《程序员》合订本上看到了这篇文章:
http://www-900.ibm.com/developerWorks/cn/linux/thread/posix_thread1/index.shtml
说是在posix里,没有父子进程这个概念,
引一段如下:
如果使用过 fork() 系统调用,可能熟悉父进程和子进程的概念。
当用 fork() 创建另一个新进程时,新进程是子进程,原始进程是父进程。
这创建了可能非常有用的层次关系,尤其是等待子进程终止时。
例如,waitpid() 函数让当前进程等待所有子进程终止。
waitpid() 用来在父进程中实现简单的清理过程。
而 POSIX 线程就更有意思。
您可能已经注意到我一直有意避免使用“父线程”和“子线程”的说法。
这是因为 POSIX 线程中不存在这种层次关系。
虽然主线程可以创建一个新线程,新线程可以创建另一个新线程,
POSIX 线程标准将它们视为等同的层次。
所以等待子线程退出的概念在这里没有意义。
POSIX 线程标准不记录任何“家族”信息。
缺少家族信息有一个主要含意:如果要等待一个线程终止,
就必须将线程的 tid 传递给 pthread_join()。线程库无法为您断定 tid。
看完我立马就晕了(LINUX是基于POSIX的,win2k呢?)
前几天有网友在LINUX下写了一个程序(原来的帖子找不到了,但伪码可以大致如下):
my_thread:
clone();
kill_myself();
MY_threads_clone(declare_my_condition);
很奇怪的是,
在父线程自杀以后,子线程的输出仍然可以进行
不知到底是什么原因,是否与上边的问题也有关系.
请各位帮忙解惑,不胜感激
线程是指程序的执行线索,本身没有父子关系,就算是用户级线程,也没有,用户级线程的实现一般是靠线程库来实现的。你调用了该线程库提供的终止线程的操作,一般不会引起别的县城被干掉,因为系统其实不知道发生了这样子的事情。但是用户级线程会有一个弊端,一旦一个线程被阻塞,整个程序就被阻塞了。用户级线程的优势是调度性能非常高,也就是说,线程切换基本没有开销。
对于核心级线程,一个死掉并不会导致另一个死掉。但是OS/2有一个所谓的主线程的概念,一旦主线程死掉,整个进程就死掉了,当然,隶属于该进程的所有线程也被干掉。核心级的线程和用户级的线程的优缺点正好相反。
线程概念上就没有父子之分,它只是被创造出来的一个执行线索。按照WindowsNT的概念,进程仅仅是一个容器,是一个执行环境,真正的执行都是线程。所以,线程一定是由线程创建的。如果创建者死了,被创建者也得死的话,你可以设想一下,你的程序在有生之年线程一定会越来越多。:)每一个线程都是由其“父”创建的。:
应该是父进程的吧
我怎么觉得子线程不退出是缺省的啊?呵呵。父线程退出时子线程是否退出取决于程序员的需要。系统只是预设一种大多数情况下方便的决定而已。这和它是不是内核线程无关。另外,子线程共享父线程的地址空间是可以的,不过对这个空间的资源回收是由操作系统决定的,和线程是否退出了没有必然关系。
unix下进程之间设父子关系很大程度上方便了编程,比如说用户操作shell时自己的登录session突然被终止了,这时侯shell的子进程就会跟着shell父进程一起退出,否则就占用系统资源了。当然,也可以指定nohup让子进程脱离父子关系,这样它就不会在父进程退出后跟着退出了。
Windows 系统中子进程依赖父进程的
Linux线程在核内是以轻量级进程的形式存在的
关于linux 线程我以前写过一篇文章,作为资料
如果,有兴趣的话,我email出来,不过我觉得我写得比较烂
Unix/Linux下线程没有怎么研究过,下面就windows平台下的理解说几句:
线程并无父子之称,在同一个系统中,线程与所有同优先级的线程争用CPU。线程倒是可以分主次,主线程是系统调用mainCRTStartUp建立的线程,负责调用main,main退出后调用exit.exit又会调用ExitProcess结束进程。所以说主线程如果下正常结束,所有的非主线程都将结束。主线程非正常结束,不能调用ExitProcess,非主线程还可以继续运行。
但现在要请教的是如何杀死主线程,请看如下代码:
void Bounce( void *para )
{
while(1)
{
Sleep( 1000L );
cout<<"The sec thread is living!"<<endl;
//WaitForSingleObject(handle,INFINITE);
}
}
void main()
{
handle=(HANDLE)_beginthread(Bounce, 0, (void *)0 );
ExitThread(1);
//WaitForSingleObject(handle,INFINITE);
}
第二个线程可以一直运行,说明主线程确实没有调用ExitProcess.但从任务管理器中查看该进程竟然还有两个线程。在第二个线程中调用WaitForSingleObject(handle,INFINITE);的话,线程会阻塞,那这种情况下,主线程确实被杀死了吗?请高手指教~
思考中......
太乱了。。。
线程是在进程中运行的,进程都翘了毛将焉附
你自己想想,程序运行代码也是要加载进内存的,线程的执行代码也在进程的内存空间,进程翘了内存释放了那还运行什么东东?
除非你CreateRemoteThread,不过那也是因为毛找到“新的归宿”,在人家加里跑才可以继续生存的
弯月兄弟,能不给我寄一份呀,我是大菜,呵呵shenxinon@hotmail.com
to cwanter(亚玛逊河上的渔夫):
我的代码如下:
#include <windows.h>
#include <process.h>
#include <stdio.h>
#include <conio.h>
unsigned __stdcall threadFunc( void *para )
{
char c;
while(1)
{
Sleep( 1000L );
printf("The second thread is living!\n");
printf( "Please input a character. \"0\" means exiting: " );
if ( ( c = getche() ) == 0 )
{
_endthreadex(0);
}
printf( "\n" );
}
}
int main()
{
HANDLE hThread;
unsigned threadID;
hThread = ( HANDLE ) _beginthreadex ( NULL, 0, threadFunc, NULL, 0, &threadID );
while(1)
{
printf( "The first thread is living before \"_endthreadex(0);\"!\n" );
#if 1
_endthreadex(0);
#else
ExitProcess(0);
#endif
printf( "The first thread is living after \"_endthreadex(0);\"!\n" );
}
printf( "If the first thread had existed, this state should be printed!\n" );
}
自己运行一下就明白了。
另外,应该杜绝使用_beginthread,而使用_beginthreadex,另外,退出线程的函数也应该对应。
在unix上如果你用posix线程的话,如果父线程结束了话,那么自线程肯定要推出的
如果你用pthread_kill杀掉同一个父线程创建出的一组子线程其中的一个,那么这一组子线程都会退出。
线程是共享同一个进程的地址空间的,主线程都被干掉了,子线程还怎么存活了?
主线程退出,子线程也会退出,也就是说你们的main中return了,不会等待子线程的反应。