Windows的进程线程优先级与修改

如果你曾经用过windows的任务管理器,就算是没有学习过windows的内核你也应该有听说过“进程优先级“这么一个概念。虽然你可能没有操作过,但是你很有可能在任务管理器里面见过它。今天稍微讲一下Windows的进程优先级以及线程优先级。

Windows是一个抢断式多线程操作系统,在并发的处理的时候最基本的执行单结构是线程,而一个进程内并不是一个执行上不可分割的结构,而是由多个线程组成的。每一个线程在内核中有一个优先级顺序,这个顺序的取值范围是0-31,数字越大优先级越高。如果有任意一个高顺序的线程需要执行,Windows绝对不会执行低优先级的线程。如果低优先级的线程一直不能被执行,那么线程就被饥饿了,这个时候抢占式操作系统的特点就体现出来了。

但是为什么平时都没有注意到呢,这里很大的原因是平时绝大多数工作线程的的优先级都是基本差不多一致的,每一个线程基本都能分配到时间片。但是有的时候我们需要创建一些较高优先级或者较低优先级的线程用来完成一些特殊的任务,我们就要了解一下这个线程的优先顺序到底是如何计算出来的。

虽然说这个优先顺序的取值范围是0-31,但是你并不能直接通过API来设定优先顺序。你能够设定一个进程优先级以及一个线程优先级。下面是一个Windows的优先级对应表:

线程相对

优先级

进程优先级类

Idle

Below Normal

Normal

Above Normal

High

Real-Time

Time-critical

15

15

15

15

15

31

Highest

6

8

10

12

15

26

Above normal

5

7

9

11

14

25

Normal

4

6

8

10

13

24

Below normal

3

5

7

9

12

23

Lowest

2

4

6

8

11

22

Idle

1

1

1

1

1

16

从这个表你可以看出来,实时优先级的进程拥有者极高的数值,通常情况下你不应该把你的进程优先级设置为实时。包括磁盘IO、鼠标显示、音频输出之类的系统功能都在实时优先级中的某些优先级中工作。如果你的线程优先级高于它们,并且需要大量CPU运算很有可能导致整个操作系统无法响应。不过微软在windows vista开始引入UAC之后开始限制了管理员账户的一些权限,现在你必须需要完全的UAC管理员权限才能把进程的优先级设置为实时,否则系统不会报错,但是最高会给你设置到高。

设置优先级的方法也非常简单,一种方法是创建进程或者创建线程的时候进行设置,另一种方法是通过专门的设置优先级的API进行设置。这里只介绍第二种通过专门的API设置的方法。

下面我给一种设置进程优先级的代码

	//提升自身优先级到实时
	HANDLE hProcess = OpenProcess(PROCESS_SET_INFORMATION, FALSE, GetCurrentProcessId());
	if (SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS) == 0)
	{
		MessageBeep(0);
		MessageBox(0, L"设置进程优先级错误,推荐手动通过进程管理器设置优先级为实时", L"警告", 0);
	}
	CloseHandle(hProcess);

类似的你也可以通过

  • SetProcessPriorityBoost
  • SetThreadPriorityBoost
  • SetThreadPriority
  • SetPrioriytClass

等这一簇函数来完成。更详细资料请参考MSDN

 

GDI高效内存手动绘图

最近一直想要写几篇文章,但是由于懒癌的发作一直都没有写。今天趁着写代码写的闹心并且无力追番的闲心写一下。

最近在参加一个比赛,里面要求百万的图形能够在10s以内能够进行裁剪显示,这对于GDI绘图来说是基本不现实的,不过经过各种优化我在1秒以内完成这个任务(i7 四核 1.8GHz)。实现这个效果的最关键的就是手动绘图替代掉效率底下的GDI。

如果有DOS下图形编程经验的朋友可能都习惯用最基本的绘点函数来完成一些复杂的绘制,到了windows之后遇到GDI之后却发现绘点函数慢的恐怖。比如要SetPixel来绘制一个调色盘,这个效率基本是要让人疯掉的。

这里先分析一下GDI的效率为什么低下。众所周知,现在的Windows是运行在保护模式的,只有系统内核以及驱动程序才能接触到那些关键的显存,而普通的ring3应用程序必须通过操作系统的API才能调用硬件资源。于是每次绘图的时候程序都会调用gdi的dll,这个动态链接库会接受到调用之后在缓冲队列里面记录下操作,在特定的时候会触发CPU陷阱把缓冲队列的数据交给内核来执行。也就是说大量的GDI绘图指令会导致大量的内核切换的开销。

为了加速绘图微软公司也是有不少解决方案,在windows早期就提出过DirectX用来直接操作这些硬件资源。不过今天并不打算采用那种复杂到恐怖的东西。还是用类似于双缓冲的方式实现

GDI里面的重要的一个概念就是DC,而DC需要一个实际的数据区,这个数据区就是一个位图。如果我们能够直接对这个位图内部的内存进行读写那么就能够非常快的完成绘图操作。

关键的代码有下面这几个,如果有问题可以查询MSDN。我一开始也对这几个函数比较有疑惑,现在稍微记录一下吧。

  • CreateCompatibleDC能够创建一个空的兼容的DC,但是这个DC由于没有缓存区所以大小是1*1的。
  • CreateCompatibleBitmap能够创建一个大小一致的兼容的BMP,由于新创建的DC并没有大小,请注意这里要传入旧的DC
  • SelectObject用来把一个BMP绑定到DC上
  • BitBlt用来复制并且光栅操作
  • SetBitmapBits用来设置一个BMP的内容

还有一些其他的API可能也是有用的,不过由于调用并没有这里方便于是我就不介绍了

代码Demo可以看我当时写的代码:https://github.com/manageryzy/lineCircle/blob/master/lineCycle/draw/drawMemory.cpp

 

Microsoft Azure Dreamspark试玩

几个月之前微软宣布Azure在Dreamspark上免费了,抱着试试看的态度几个月之前就打算弄一个玩玩。不过由于中国的特殊情况,中国地区的Azure是由世纪互联运营,但是世纪互联并不认Dreamspark的活动,于是需要一个其他地区的手机号用来验证账户。

网络上有一些虚拟电话号码用来接收短信,不过由于他们大多是VOIP号码被微软禁止使用,所以我一狠心花了三十大洋买了一个香港的手机卡。

注册账号这个没什么说的。去Dreamspark网站一进去就能看到Azure了,激活账号的时候验证手机号,Dreamspark注册Azure不需要信用卡,否则还要信用卡进行验证。注册完账号之后微软要求等几分钟。大概等待了两分半中后账号就绪了。这个时候可以通过访问https://portal.azure.com/ 进入后台。

QQ图片20150502020340

进后台的过程由于网速原因简直就是煎熬。我花了整整十分钟才进入。

QQ图片20150502020340

费半天劲终于成功的进入了主面板。各种操作由于网速的原因……不说了,说多了都是泪

下面看一下Azure Dreamspark提供的免费服务。Dreamspark版本的Azure相当多的内容都不能用,能用的只有最低配置的Web程序以及数据库。大概和烂大街的免费主机是一个水平的。网速上Azure也没有明显的优势。这可能和我选择的节点有关吧,我选择的是日本西部地区可能速度不如亚洲南部地区。总之Azure Dreamspark版本是相当坑爹的东西啦

Microsoft Visual Studio Code Linux上手试玩

在微软2015 build大会上微软推出了最新的跨平台的代码编辑器:Visual Studio Code。这个编辑器可以在Windows、Linux、OS X上运行。

QC)EJ@XDD0KYQ_GAHXAAT5Q

访问visual studio的网站马上就能看到这个的下载页面,下载linux版之后会得到一个zip包(不是tar.gz差评)。解压缩之后能看到一个叫做code的文件,文件已经默认有了执行权限,在ubuntu下面只要双击就可以运行。

虽然说visual studio code是一个编辑器,但是它还是很好的继承了visual studio的一大特色——慢。不过还好只是启动比较慢。运行的速度不是很慢。这可能是由于我的ubuntu分区不是在SSD上的原因吧。启动软件花了我十多秒,并且一开始的时候没有任何提示。这让我以为我没有启动成功。

编辑器的界面总体上讲非常的清爽,没有一坨坨的按钮,只有必要的编辑、浏览、git和调试。

QQ图片20150502020340

怎么说呢,这个界面觉得好像IE的F12的……

使用起来的话初学者可能有一点比较麻烦,这里没有一个个的先导。系统会默认的把项目的配置文件生成并且存在.setting目录下面。项目的配置以及启动配置都是json文件。虽然有英文的说明,但是你不得不把这些全都读一遍。(真是满满的linux的感觉,雾)

编辑器支持许多web开发技术:从nodejs到sass,基本囊括了所有前端后端的最热门的web新技术,代码提示也很好用,而且在没有reshape的时候代码提示就已经能用了(黑vs黑的丧心病狂),但是,他只能开发web,只能开发web,只能开发web(因为很重要,所以要说三遍,但愿不要被微软光速打脸)

总之有时间那它撸个nodejs的项目玩玩好了,刚上手的感觉还算是不错