关于线程的执行和退出
2010-07-02 00:07
155 查看
线程由两部分构成:
线程内核对象:操作系统用它来对线程实施管理。内核对象也是系统用来存放线程统计信息的地方。
线程堆栈:它用于维护线程在执行代码时需要的所有函数参数和局部变量。
我们必需要知道一个事实
-----
进程(
WINDOWS
中)是不能被调度的。通常所说的调度,都是对线程而言的。进程仅仅是线程的容器,是系统统分配资源的单位。
这样,线程自身不会分配资源。同一进程中的多个线程共同使用它们父进程的资源。
一个进程至少需一个线程,如果一个进程中不存在线程(所有线程都退出)。则系统认为这个进程没有存在的必要,于是便会撤消这个进程,并释放他占用的资源。
在
VC
环境中,我们可以调用
CreatThread
来创建一个线程。关于用法请查
MSDN
我们应该主要关注这个
API
的调用,操作系统会干哪些事情。而不是仅仅会使用这个
API
。
当程序启动的时候,系统会创建一个进程,进而会为这个进程创建一个主线程。主线程即是一个程序的入口。
C/C++
运行期库会初始化全局的
C/C++
变量,然后调用入口点函数(如
main
)。然后初始化线程堆栈,创建临时变量等。
当线程结束时会按以下操作执行。
1、
在线程函数中创建的所有
C++
对象均将通过它们的撤消函数正确地撤消。
2、
操作系统将正确地释放线程堆栈使用的内存。
3、
系统将线程退出代码设置为线程函数的返回值。
4、
系统将递减线程内核对象的引用计数。
因此,正确的线程退出方式是必不可少的。
最好的退出线程的方法是让线程函数返回,这样
C/C++
运行期库便能正确地撤消
C/C++
对象。
值一说的是,不管线程怎么退出,当一个程序结束时,系统总是回清除他使用了的系统资源,如内核对象等。但
C/C+=
运行期库申请的资源则不会被释放。
像
ExitThread
等函数,需要三思而用。
众所周知,创建线程的时候,必不可少的两个参数就是线程入口函数和函数参数。那这两个是怎么工作的呢。请看如下分析。
首先要知道,每个线程都有自己的一组
CPU
寄存器。这组寄存器的所有信息就是我们所说的线程上下文。当系统进行时间片轮转执行线程的时候,会将前一个线程的所有寄存器值保存,然后将下一个需要执行的线程的寄存器值装入
CPU
寄存器,进而执行。重复这样的操作,就达到了多线程执行的效果。当然,实际情况是很复杂的。需要许多的判断,在多处理器计算机中,还需要考虑线程的亲缘性等。
话不多说,回头来看这个线程函数的执行方式。
当一个线程被创建时,系统便会创建线程的内核对象。并分配线程堆栈需要的内存。这个内存是从进程的地址空间分配而来的,因为我们知道,线程不持有资源。当一切都做好后,便是填写数据了。
系统首先会把线程的参数和入口地址压入线程堆栈。
注意,是先压的参数,再压的入口地址。这样入口地址是在栈顶。此时
SP
的值即为函数入口地址。
而将
IP
设置为另一个函数。它叫
void BaseThreadStart();
很神奇吧,为什么
IP
并不是线程的入口函数地址呢。
我们直接可以猜到,
void BaseThreadStart();
所做的工作中,会调用到我们的线程入口函数。接下来我们看看
void BaseThreadStart();
函数干了些什么。
void BaseThreadStart(PTHREAD_START_ROUTINE pfnStartAddr,PVOID pvParam)
{
__try{
Exithread((pfnStartAddr)(pvParam));
}
__except(UnhandedExceptionFilter(GetExceptionInformation()){
ExitProcess(GetExceptionCode());
}
}
还记得我们压栈的时候是先压的参数再压的线程函数入口地址么。这就对了,上面即是这样的情况。
可以看出,
BaseThreadStart
函数不会马上返回,他会等待线程结束后返回。由于线程和进程共用的进程内存空间,可以知道。如果线程函数没有退出
BaseThreadStart
就返回,可以肯定的会引发访问违规。因为线程未退出时,线程堆栈并未清除。
BaseThreadStart
返回时,从堆栈上得到的返回地址是一个不可预测的值。
进程在初始化时也会是类似执行方式。因为进程执行时,启动的是一个主线程,而不是由进程本身来执行代码。
最后说明,当新线程执行
BaseThreadStart
函数时,将会出现如下情况:
1、
在线程函数中建立一个
SHE
,这样,在线程执行时产生的任何异常情况都将会得到系统的某种默认处理。
2、
系统调用线程函数,并将你传递的参数传递给它。
3、
当线程函数返回时,
BaseThreadStart
调用
Exithread
,并将线程函数的返回值传递给它。该线程内核对象的使用计数减
1
,线程停止运行。
4、
如果线程产生一个没有处理的异常条件,由
BaseThreadStart
建立的
SHE
将负责处理该异常。由上面可以看出,它调用
ExitProcess
退出整个进程。
线程内核对象:操作系统用它来对线程实施管理。内核对象也是系统用来存放线程统计信息的地方。
线程堆栈:它用于维护线程在执行代码时需要的所有函数参数和局部变量。
我们必需要知道一个事实
-----
进程(
WINDOWS
中)是不能被调度的。通常所说的调度,都是对线程而言的。进程仅仅是线程的容器,是系统统分配资源的单位。
这样,线程自身不会分配资源。同一进程中的多个线程共同使用它们父进程的资源。
一个进程至少需一个线程,如果一个进程中不存在线程(所有线程都退出)。则系统认为这个进程没有存在的必要,于是便会撤消这个进程,并释放他占用的资源。
在
VC
环境中,我们可以调用
CreatThread
来创建一个线程。关于用法请查
MSDN
我们应该主要关注这个
API
的调用,操作系统会干哪些事情。而不是仅仅会使用这个
API
。
当程序启动的时候,系统会创建一个进程,进而会为这个进程创建一个主线程。主线程即是一个程序的入口。
C/C++
运行期库会初始化全局的
C/C++
变量,然后调用入口点函数(如
main
)。然后初始化线程堆栈,创建临时变量等。
当线程结束时会按以下操作执行。
1、
在线程函数中创建的所有
C++
对象均将通过它们的撤消函数正确地撤消。
2、
操作系统将正确地释放线程堆栈使用的内存。
3、
系统将线程退出代码设置为线程函数的返回值。
4、
系统将递减线程内核对象的引用计数。
因此,正确的线程退出方式是必不可少的。
最好的退出线程的方法是让线程函数返回,这样
C/C++
运行期库便能正确地撤消
C/C++
对象。
值一说的是,不管线程怎么退出,当一个程序结束时,系统总是回清除他使用了的系统资源,如内核对象等。但
C/C+=
运行期库申请的资源则不会被释放。
像
ExitThread
等函数,需要三思而用。
众所周知,创建线程的时候,必不可少的两个参数就是线程入口函数和函数参数。那这两个是怎么工作的呢。请看如下分析。
首先要知道,每个线程都有自己的一组
CPU
寄存器。这组寄存器的所有信息就是我们所说的线程上下文。当系统进行时间片轮转执行线程的时候,会将前一个线程的所有寄存器值保存,然后将下一个需要执行的线程的寄存器值装入
CPU
寄存器,进而执行。重复这样的操作,就达到了多线程执行的效果。当然,实际情况是很复杂的。需要许多的判断,在多处理器计算机中,还需要考虑线程的亲缘性等。
话不多说,回头来看这个线程函数的执行方式。
当一个线程被创建时,系统便会创建线程的内核对象。并分配线程堆栈需要的内存。这个内存是从进程的地址空间分配而来的,因为我们知道,线程不持有资源。当一切都做好后,便是填写数据了。
系统首先会把线程的参数和入口地址压入线程堆栈。
注意,是先压的参数,再压的入口地址。这样入口地址是在栈顶。此时
SP
的值即为函数入口地址。
而将
IP
设置为另一个函数。它叫
void BaseThreadStart();
很神奇吧,为什么
IP
并不是线程的入口函数地址呢。
我们直接可以猜到,
void BaseThreadStart();
所做的工作中,会调用到我们的线程入口函数。接下来我们看看
void BaseThreadStart();
函数干了些什么。
void BaseThreadStart(PTHREAD_START_ROUTINE pfnStartAddr,PVOID pvParam)
{
__try{
Exithread((pfnStartAddr)(pvParam));
}
__except(UnhandedExceptionFilter(GetExceptionInformation()){
ExitProcess(GetExceptionCode());
}
}
还记得我们压栈的时候是先压的参数再压的线程函数入口地址么。这就对了,上面即是这样的情况。
可以看出,
BaseThreadStart
函数不会马上返回,他会等待线程结束后返回。由于线程和进程共用的进程内存空间,可以知道。如果线程函数没有退出
BaseThreadStart
就返回,可以肯定的会引发访问违规。因为线程未退出时,线程堆栈并未清除。
BaseThreadStart
返回时,从堆栈上得到的返回地址是一个不可预测的值。
进程在初始化时也会是类似执行方式。因为进程执行时,启动的是一个主线程,而不是由进程本身来执行代码。
最后说明,当新线程执行
BaseThreadStart
函数时,将会出现如下情况:
1、
在线程函数中建立一个
SHE
,这样,在线程执行时产生的任何异常情况都将会得到系统的某种默认处理。
2、
系统调用线程函数,并将你传递的参数传递给它。
3、
当线程函数返回时,
BaseThreadStart
调用
Exithread
,并将线程函数的返回值传递给它。该线程内核对象的使用计数减
1
,线程停止运行。
4、
如果线程产生一个没有处理的异常条件,由
BaseThreadStart
建立的
SHE
将负责处理该异常。由上面可以看出,它调用
ExitProcess
退出整个进程。
相关文章推荐
- 关于线程的执行和退出
- 关于线程的执行和退出
- 关于在子线程中在run方法执行完之后通知主线程进行操作的方法。(Toast在子线程中无法使用)
- 关于java中怎么终止一个线程的执行
- ABC线程如何保证顺序执行 关于多线程的一个小例子
- 修补bug之路——关于线程执行函数全局的问题
- 关于Java线程意外退出自动重启..
- 关于for 循环里 线程执行顺序问题
- 问题和解决 ROS节点的不可执行(线程退出)
- linux线程退出时执行的程序(线程清理处理程序)简单例子
- 关于app退出后子线程停止的问题
- (委托事件处理)关于多线程执行显示进度条的实例(转)&&线程间操作无效: 从不是创建控件“rtxtEntryNO”的线程访问它。
- 关于java线程的经典面试题。主线程子线程交替执行n次
- 关于线程退出的问题
- 关于强制退出线程操作的代码
- 【Win32多线程】创建线程、获取线程执行状态、退出线程、错误处理
- 关于GCD同步组实现多个异步线程的同步执行中的注意点
- AutoResetEvent信号锁 waitone set 执行一次线程退出 挺不爽的地方
- GCD退出线程执行
- 线程等待一定时间和及时返回继续执行,以及等待线程退出。