Kernel module编程(十二):并发和竞争控制

  本文也即《Linux Device Drivers》,LDD3的第五章Concurrency and Race Conditions的读书笔记之一,但我们不限于此内容,最近正在整理移动手机的业务需求,比较多的文档工作,没什么时间学习。有本好书推荐一下,就是 钱穆先生的《中国历代政治得失》,书很薄,但是内容很丰富,推荐推荐。

   并发引发的bug是OS程序中一个主要的问题并且很难发现。其实在我们的应用中也是如此。我有一个JAVA的SIP AS的项目,在大话务量的测试中,一直只有6个9,及99.9999x%,无论我提供呼叫压力,还是适当减少,都能跟踪到报错exception的情况, 当然能通过异常处理恢复,不会对下一session有影响。对于电信级别的设备,6个9实际上也是非常满意的,但是我不明白计算机的0101,为什么会出 现问题,根据测试环境所有的session都是按正常流程的,很奇怪。可能前后也花了1年多的时间提高性能(查这个问题可能也花了近1个月,那段时间比较 有空),最后发现问题就在并发上,这不仅是多线程的而且是多进程的。在这不知道多少行的庞大的代码,出问题的部分其实处理很简单的内容,就是index依 次加1,达到一个门限的时候置0,重新开始,问题是在多线程的处理下有千万分之几的概率有出现超过门限的情况,只需要将两行前后语句顺序换个位置就可以解 决,后来我有压了上亿个session(感谢Abacus仪表啊,^_^),没有出现一个错误。

   这只是程序的性能更好的问题,但是如果不能对并发进行控制,引起竞争,后果是很严重的,例如同时malloc了内存,但是实际上最后只能释放其中的一个内 存,这会引发内存泄漏,任何内存泄漏的程序都是不稳定,无法长期执行的。如果情况更坏,free了另一个地址的,将可能引发系统的crash。这些错误可 能在程序运行的任何时候发生,不容易定位。引起并发竞争包括下面的原因:一、多个用户控件的进程执行,可能以各种组合方式来触发你的内核程序;二、多 CPU并发处理;三、在执行过程中CPU被其他强占,可能在任何情况下继续,也就是你在顺序执行某个函数过程中,随时可能有新的触发;四、对于热插拔的设 备,可能驱动正在执行某段程序时,该设备被拔掉不复存在。任何时候都可能发生任何事情,因此我们的开发要遵循一些原则来避免:【编程思想:对竞争的处理原则】

一、尽可能在程序中避免共享资源(数据、硬件), 竞争就由共享资源引发的,只要没有共享资源就没有竞争危险,在我们的程序中,应尽可能减少global数据的使用 ,这在所有程序开发中都需要遵循。最近我正在跟踪一个JAVA上的BUG,在一个网络连接类的构造函数中传递了某个对象,有些状态通过这个对象的某个属性 来记录,在网络不稳定的情况下,出现稳定,即使我设计这个连接类有自动恢复的功能。一开始client和server之间只有一条TCP连接,所有这种方 式不会出现任何问题,后来将他们之间连接数增加为10条复用,这个错误就是BUG。当然导致这个出现是因为后来改变框架设计,而对原来的代码也不会如此细 致考虑。但是如果在开始就遵循这条设计原则见过不会发生。可以想象,如果开始和后来是两个不同的开发人员,查找的难道就很大了。

二、当共享资源(数据或者硬件)可以在多个线程/进程中执行,在其中一个线程可能出现不连续使用该资源时,需要精确地管理资源的获取。通常是通过加锁或者互斥方式,保证该共享资源只有一个线程在执行。也就是说:当必须共享资源的时候,要确保在资源的连续操作(例如程序的一个函数,或一段或者多段的处理)中只有一个线程。

三、一个对象只要外部仍有引用将一直存在,也就是说:当我们释放一个对象时,必须保证外部已经没有引用。在JAVA中,garbage的自动回收就是基于此机制。在C/C++我们必须仔细地规划。

你可能感兴趣的:(多线程,编程,网络应用,读书,中国电信)