月度归档:2011年05月

线程、线程句柄、线程ID

什么是句柄:

句柄是一种指向指针的指针。我们知道,所谓指针是一种内存地址。应用程序启动后,组成这个程序的各对象是住留在内存的。如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访问对象。但是,如果您真的这样认为,那么您就大错特错了。我们知道,Windows是一个以虚拟内存为基础的操作系统。在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。对象被移动意味着它的地址变化了。如果地址总是如此变化,我们该到哪里去找该对象呢?
为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,用来专门登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。Windows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。这样我们只需记住这个句柄地址就可以间接地知道对象具体在内存中的哪个位置。这个地址是在对象装载(Load)时由系统分配给的,当系统卸载时(Unload)又释放给系统。
句柄地址(稳定)→记载着对象在内存中的地址→对象在内存中的地址(不稳定)→实际对象
线程与线程句柄的关系:

句柄可以认为是系统对资源(如线程)的分配的一个编号。关闭这个编号,对于不同的资源,效果不尽相同。对于线程来说,关闭这个编号并不意味着终止线程,只是之后很难再操纵这个线程。
线程句柄与线程ID的区别:
CreateThread() API 用于创建线程。 API 返回同时线程句柄和线程标识符 (ID)。线程句柄有完全访问权创建线程对象。 运行线程时线程 ID 唯一标识线程在系统级别。
●ID是在Windows系统范围内唯一标示Thread的。
●Handle是用来操作Thread的,可以有多个,每个HANDLE可以有不同的操作权限,在不同进程OpenThread得到的值不一样。
●线程的ID是系统全局的,其HANDLE是进程局部的.

●此ID只在线程的生存期内有效。

●HANDLE是os和client之间用来操作进程和线程一个桥梁,os有一张维护HANDLE的表单,里面大概放置了  HANDLE的引用计数和有关的属性,HANDLE是os标识进程和线程的东西,但是用户也可以用这个来标识进程和线程,对其操作;而ID是os用来标识进程和线程的,并且是全局唯一的,  但用户可以通过这个ID获得进程线程的HANDLE,多次得到的HANDLE并不一定是一样的.HANDLE是内核对象,而ID好像不是,并没有专门创建ID的函数.

●ID是CreateThread时操作系统自动生成的。

●线程的句柄和id是不同的。
在windows系统中,线程的id是唯一对应的,也就是说,如果两个线程返回相同的id,则他们必然是同一线程,反之一定是不同的线程。而线程的句柄并不是线程的唯一标识,线程的句柄只是用来访问该线程的的一个32位值,尽管相同的句柄一定标识同一线程,但同一线程可能拥有两个打开的句柄,因此,不能用句柄来区分两个线程是否是同一线程。
线程终止运行时发生的操作
  当线程终止运行时,会发生下列操作:
• 线程拥有的所有用户对象均被释放。在 Windows 中,大多数对象是由包含创建这些对象的线程的进程拥有的。但是一个线程拥有两个用户对象,即窗口和挂钩。当线程终止运行时,系统会自动撤消任何窗口,并且卸载线程创建的或安装的任何挂钩。其他对象只有在拥有线程的进程终止运行时才被撤消。
• 线程的退出代码从 STILL_ACTIVE 改为传递给 ExitThread 或 TerminateThread 的代码。
• 线程内核对象的状态变为已通知。
• 如果线程是进程中最后一个活动线程,系统也将进程视为已经终止运行。
• 线程内核对象的使用计数递减 1。
当一个线程终止运行时,在与它相关联的线程内核对象的所有未结束的引用关闭之前,该内核对象不会自动被释放。
一旦线程不再运行,系统中就没有别的线程能够处理该线程的句柄。然而别的线程可以调用 GetExitcodeThread 来检查由 hThread 标识的线程是否已经终止运行。如果它已经终止运行,则确定它的退出代码:
BOOL GetExitCodeThread(HANDLE hThread, PDOWRD pdwExitCode);
退出代码的值在 pdwExitCode 指向的 DWORD 中返回。如果调用 GetExitCodeThread 时线程尚未终止运行,该函数就用 STILL_ACTIVE 标识符(定义为 0x103)填入 DWORD。如果该函数运行成功,便返回 TRUE。

    线程退出的时候内核对象就会被激发, WaitForSingleObject()为堵塞函数,等待线程的内核对象被激发。所以终止线程并释放句柄对象的顺序是:TerminateThread()–>WaitForSingleObject()–>CloseHandle().

线程、线程句柄、线程ID的生成和消失

hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, &dwId);

//至此,新线程,线程句柄,线程ID产生

TerminateThread(hThread, 0);
//至此,线程ID,线程句柄都依然存在

WaitForSingleObject(hThread, INFINITE);

//至此,线程本身和线程ID消失

CloseHandle(hThread);
//至此,线程句柄消失

 

转自:http://blog.sina.com.cn/s/blog_4e0494e00100jig5.html

openvpn的tap驱动导致的系统网络异常

今天玩起了openvpn,以前一般不用这个的,我一般比较喜欢pptp的vpn.

因为无需下载运行任何的客户端,只需要在系统中设置即可使用。

今天尝试在vps上自己搭建openvpn,于是电脑上也装上了官方的openvpn客户端。

 

后来又尝试了一个服务商proXPN,他自己提供了自有的客户端的下载,后来才发现他也是基于openvpn的。

而且,这个貌似不好用,遂将其卸载,但是这个程序在卸载的过程中把我的tap驱动也一并卸载了,并且在卸载过程中卡住了很久没有动。

 

后面系统开始异常,系统托盘区无法点开网络连接,控制面板也无法打开网络连接。

重启后系统异常加重,发现进程数只有20多,不要高兴,在win7上面,加上华硕的自带套件,在我优化过后也应该是有40多进程的。

 

后面发现许多程序无法打开,网络显示连接不上。在windows服务里面发现多项windows自动启动的服务没有启动,包括事件日志。

 

后面我用手机查了下,用了一条命令 netsh winsock reset重置winsock

重启电脑后异常消失

解决itunes升级ios不能续传和下载慢的问题

今天料爷告诉我要升级她的爱疯。但是下载更新过程超级慢,她是校园网的用户。

开始还必须用free g番茄出去才可以连接的到。

他说要下载3-4个小时还经常会失败,我发现itunes在下载这个ios升级文件的时候不能断点续传。

按了暂停以后再开始又会重头下载,用vpn速度稍微理想但是还是很慢,下了30分钟以后vpn断了,杯具鸟。

 

再去找vpn发现很多都是限制流量例如300m,但是那个升级文件要402m。

 

在网上看到有人是通过一个地址直接下载那个固件再用离线升级的办法,网上公布了很多地址但是不知道哪个是合适的。

遂自己抓包分析地址,居然没抓到数据,后面使用了我写的一个程序网络中间人,成功获得了下载地址。

我这个程序的原理是,一个网络中间件,在做数据转发的过程中抓取数据。

 

我的具体实施过程是:

1,开fg,他的本地端口为8580

2,开我这个工具,按图把远程地址端口设好127.0.0.1  8580  然后再开一个本地端口8880

3,在ie的代理选项中把fg给设置的代理127.0.0.1端口8580改成8880

4,itunes里面开始下载,然后网络中间人程序就能捕捉到数据。

 

在第一个数据包那里看见了下载地址,然后我使用了迅雷下载,由于迅雷的加速,这个文件下的好快

 

 

 文件名称: iPhone2,1_4.3.3_8J2_Restore.ipsw
下载状态: 下载完成
文件大小: 420.11MB
存储目录: D:/
创建时间: 2011-05-06 16:33:33
完成时间: 2011-05-06 16:53:19
下载用时: 19分12秒
平均速度: 373.43 KB/s
URL:http://appldnld.apple.com/iPhone4/041-1009.20110503.M73Yr/iPhone2,1_4.3.3_8J2_Restore.ipsw
下载来源:
注释:
很快的就下载好了,不理解为什么itunes不能断点续传。
关于升级,根据网上的说法,按住shift按键再点击更新按钮,就会出现文件打开对话框
然后你就可以选择下好的本地文件进行更新