如何关闭linux smp中断,第1张

在多 CPU 的环境中,还有一个中断平衡的问题,比如,网卡中断会教给哪个 CPU 处理,这个参数控制哪些 CPU 可以绑定 IRQ 中断。其中的 {number} 是对应设备的中断编号,可以用下面的命令找出:

cat /proc/interrupt

比如,一般 eth0 的 IRQ 编号是 16,所以控制 eth0 中断绑定的 /proc 文件名是 /proc/irq/16/smp_affinity。上面这个命令还可以看到某些中断对应的CPU处理的次数,缺省的时候肯定是不平衡的。

设置其值的方法很简单,smp_affinity 自身是一个位掩码(bitmask),特定的位对应特定的 CPU,这样,01 就意味着只有第一个 CPU 可以处理对应的中断,而 0f(0x1111)意味着四个 CPU 都会参与中断处理。

几乎所有外设都有这个参数设置,可以关注一下。

这个数值的推荐设置,其实在很大程度上,让专门的CPU处理专门的中断是效率最高的,比如,给磁盘IO一个CPU,给网卡一个CPU,这样是比较合理的。

现在的服务器一般都是多核了,但是中断很多时候都是只用一个核,如果有些中断要求比较高,可以把它独立分配给一个cpu使用。

很多库例程产生的“随机”数是准备用于仿真、游戏等等;它们在被用于密钥生成一类的安全函数时是不够随机的。其问题在于这些库例程使用的算法的未来值可以被攻击者轻易地推导出来(虽然看起来它们可能是随机的)。对于安全函数,需要的随机值应该是基于量子效应之类的确实无法预测的值。Linux内核(1330以上)包括了一个随机数发生器/dev/random,对于很多安全目的是足够的。

/dev/random 是如何创建随机数的呢?

Linux 操作系统提供本质上随机(或者至少具有强烈随机性的部件)的库数据。这些数据通常来自于设备驱动程序。例如,键盘驱动程序收集两个按键之间时间的信息,然后将这个环境噪声填入随机数发生器库。

随机数据存储在 熵池中,它在每次有新数据进入时进行“搅拌”。这种搅拌实际上是一种数学转换,帮助提高随机性。当数据添加到熵池中后,系统估计获得了多少真正随机位。

测定随机性的总量是很重要的。问题是某些量往往比起先考虑时看上去的随机性小。例如,添加表示自从上次按键盘以来秒数的 32 位数实际上并没有提供新的 32 位随机信息,因为大多数按键都是很接近的。

从 /dev/random 中读取字节后,熵池就使用 MD5 算法进行密码散列,该散列中的各个字节被转换成数字,然后返回。

如果在熵池中没有可用的随机性位, /dev/random 在池中有足够的随机性之前等待,不返回结果。这意味着如果使用 /dev/random 来产生许多随机数,就会发现它太慢了,不够实用。我们经常看到 /dev/random 生成几十字节的数据,然后在许多秒内都不产生结果。

幸运的是有熵池的另一个接口可以绕过这个限制:/dev/urandom。即使熵池中没有随机性可用,这个替代设备也总是返回随机数。如果您取出许多数而不给熵池足够的时间重新充满,就再也不能获得各种来源的合用熵的好处了;但您仍可以从熵池的 MD5 散列中获得非常好的随机数!这种方式的问题是,如果有任何人破解了 MD5 算法,并通过查看输出了解到有关散列输入的信息,那么您的数就会立刻变得完全可预料。大多数专家都认为这种分析从计算角度来讲是不可行的。然而,仍然认为 /dev/urandom 比 /dev/random 要“不安全一些”(并通常值得怀疑)。

应用中出现的问题:

在我们的服务器程序中,用户登陆的时候会读取/dev/random产生随机数,问题来了,当用户登陆比较密集,这时候read就会返回特别慢,并且返回的字节数也比要求的少,甚至不返回――阻塞。我们把用户登陆处理函数放在了线程池里,导致的问题就是线程池里所有线程都可能会阻塞,这就造成了拒绝服务攻击。导致其他用户登陆失败。

解决方案:

CODE:1 #include <stdioh>

2 #include <stringh>

3 #include <sys/typesh>

4 #include <sys/stath>

5 #include <sys/fileh>

6 #include <sys/timeh>

7 #include <errnoh>

8 #include <unistdh>

9 #include <stdlibh>

10

11 static int get_random_fd (void)

12 {

13 static int fd = -2;

14

15 if (fd == -2)

16 {

17 fd = open ("/dev/random", O_RDONLY | O_NONBLOCK);

18 if (fd == -1)

19 fd = open ("/dev/urandom", O_RDONLY | O_NONBLOCK);

20 }

21

22 return fd;

23 }

24

25 /

26 Generate a series of random bytes Use /dev/random if possible,

27 and if not, use /dev/urandom

28 /

29 void get_random_bytes(void buf, int nbytes)

30 {

31 int i, fd = get_random_fd();

32 int lose_counter = 0;

33 char cp = (char)buf;

34 struct timeval tv;

35 static unsigned seed = 0;

36

37 if (fd >= 0)

38 {

39 while (nbytes > 0)

40 {

41 i = read (fd, cp, nbytes);

42 if ((i < 0) &&

43 ((errno == EINTR) || (errno == EAGAIN)))

44 continue;

45

46 if (i <= 0)

47 {

48 if (lose_counter++ == 8)

49 break;

50

51 continue;

52 }

53 nbytes -= i;

54 cp += i;

55 lose_counter = 0;

56 }

57 }

58

59 for (i = 0; i < nbytes; i++)

60 {

61 if (seed == 0)

62 {

63 gettimeofday(&tv, 0);

64 seed = (getpid() << 16) ^ getuid() ^ tvtv_sec ^ tvtv_usec;

65 }

66 cp++ = rand_r(&seed) & 0xFF;

67 }

68

69 return;

70 }

13行: 定义fd为静态变量,这样只打开一次设备。

17 – 19行: 无阻塞模式打开/dev/random设备。如果该设备打开失败尝试打开/dev/urandom。

29行: void get_random_bytes(void buf, int nbytes)函数是提供给用户的接口,用户调用这个函数就可以得到随机数。

37-57行: read有可能返回的字节数小于请求的字节数。这时候就循环读直到读够了所请求的大小。这样最多重复8次。然后返回。

59-67行: 如果上面重复8次都没有读够所请求的字节数,则我们自己生成随机数来填充。

注意:打开的fd我们并没有关闭,请您根据自己需求在合适的地方关闭。

CentOS 7系统中安装好openjdk和Tomcat后,启动过程很慢,长达数分钟,日志如下:

tomcat启动耗时278084ms折合278秒,对于刚刚安装的干净tomcat,这肯定是不对劲的。

其中有一条日志引起了笔者的注意:

显然tomcat执行到这里时出问题了,google了一下,经过一番搜索明白了其中的缘由。

在tomcat官方wiki文档的 HowToFasterStartUp 章节中,Entropy Source部分有一段这样的说明:

从这里我们得知Tocmat的Session ID是通过SHA1PRNG算法计算得到的,计算Session ID的时候必须有一个密钥,为了提高安全性Tomcat在启动的时候会通过随机生成一个密钥,它强依赖于获取熵池中的随机数来进行创建。

那么什么是 /dev/random ?什么是 熵池

/dev/random

从维基百科得知,在UNIX操作系统(包括类UNIX系统)中, /dev/random 是一个特殊的设备文件,可以用作随机数生成器或伪随机数生成器。

Linux内核中的是第一个以 背景噪声 产生真正的随机数产生的实现,它允许程序访问来自设备驱动程序或其它来源的背景噪声。

Linux上有两个通用的随机设备: /dev/random 和 /dev/urandom 。其中 /dev/random 的随机性最好,因为它是一个阻塞的设备。而 /dev/random 的一个副本是 /dev/urandom (“unblocked”,非阻塞的随机数生成器),它会重复使用熵池中的数据以产生伪随机数据。这表示对 /dev/urandom 的读取操作不会产生阻塞,但其输出的熵可能小于 /dev/random 的。所以它可以作为生成较低强度密码的伪随机数生成器,不建议用于生成高强度长期密码。

熵池

熵池本质上是若干字节, /proc/sys/kernel/random/entropy_avail 中存储了熵池现在的大小, /proc/sys/kernel/random/poolsize 是熵池的最大容量,单位都是bit。如果 entropy_avail 的值小于要产生的随机数bit数,那么 /dev/random 就会堵塞。

为什么熵池不够用?

熵池实际上是从各种noice source中获取数据,noice source可能是键盘事件、鼠标事件、设备时钟中等。linux内核从24升级到26时,处于安全性的考虑,废弃了一些source。source减少了,熵池补给的速度当然也变慢,进而不够用。

其实,通过消耗熵池,可以构造DDOS攻击。原理很简单,熵池空了,依赖随机数的业务(SSL,加密等)就不能正常进行。

通过以上信息,笔者得知该问题是由于熵池不足导致的。 怎么解决?

使用非阻塞性的生成器 /dev/urandom 代替 /dev/random 。

1、可在JVM环境中配置

通过配置发生器指定熵收集守护进程

修改 $JAVA_PATH/jre/lib/security/javasecurity 中参数 securerandomsource 为:

2、也可在Tomcat环境中配置

通过配置JRE使用非阻塞的Entropy Source获取熵

在 $TOMCAT_HOME/bin/catalinash 中加入:

这个系统属性egd表示熵收集守护进程(entropy gathering daemon)。

1、[硬件随机数生成器]安装并使用rng-tools作为额外的熵随机数生成器(推荐)

cat /dev/random 命令会消耗熵池, rngd 守护进程会补充熵池,可使用如下命令来测试随机数生成的情况:

2、[软件随机数生成器]在rng-tools仍不满足的情况下,可使用haveged作为额外的熵随机数生成器

要检查是否需要 Haveged,可使用下面命令查看当前收集到的熵:

如果结果比较低 (<1000),建议安装 haveged,否则加密程序会处于等待状态,直到系统有足够的熵。

安装 haveged 之后,可以再次查看系统熵看下有无提升。

因为方法一存在一定的不安全性,且需要对环境进行配置,为了满足熵的需要,这里笔者选择了第二种方法,使用rng-tools作为额外的熵随机数生成器,同以上操作后顺利解决了问题。

操作后重启tomcat日志如下,启动速度快了两个数量级:

参考文档:

https://stackoverflowcom/questions/40383430/tomcat-takes-too-much-time-to-start-java-securerandom

https://bugsjavacom/bugdatabase/view_bugdobug_id=6202721

http://openjdkjavanet/jeps/123

https://zhwikipediaorg/zh-hans//dev/random

https://wikiapacheorg/tomcat/HowTo/FasterStartUp

https://accessredhatcom/documentation/en-us/red_hat_enterprise_linux/6/html/security_guide/sect-security_guide-encryption-using_the_random_number_generator

https://wikiarchlinuxorg/indexphp/Rng-tools

https://wikiarchlinuxorg/indexphp/Haveged

https://wwwdigitaloceancom/community/tutorials/how-to-setup-additional-entropy-for-cloud-servers-using-haveged

DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
网站模板库 » 如何关闭linux smp中断

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情