Linux 性能监控、测试、优化工具

Linux 平台上的性能工具有很多,眼花缭乱,长期的摸索和经验发现最好用的还是那些久经考验的、简单的小工具。系统性能专家 Brendan D. Gregg 在最近的 LinuxCon NA 2014 大会上更新了他那个有名的关于 Linux 性能方面的 talk (Linux Performance Tools) 和幻灯片。

和 Brendan 去年的 talk 比较,今年增加了测试和优化两部分。下面的三张图片分别总结了 Linux 各个子系统以及监控、测试、优化这些子系统所用到的工具。

监控

linux performance tools

测试

linux performance tools

优化

linux performance tools

使用 tuned/tuned-adm 工具动态调优系统

RHEL/CentOS 在 6.3 版本以后引入了一套新的系统调优工具 tuned/tuned-adm,其中 tuned 是服务端程序,用来监控和收集系统各个组件的数据,并依据数据提供的信息动态调整系统设置,达到动态优化系统的目的;tuned-adm 是客户端程序,用来和 tuned 打交道,用命令行的方式管理和配置 tuned,tuned-adm 提供了一些预先配置的优化方案可供直接使用,比如:笔记本、虚拟机、存储服务器等。

如果你正在使用笔记本(电池电源),想优化系统、节约电源又不想知道太多这方面的细节,就可以用 tuned/tuned-adm 这套工具并应用 laptop-battery-powersave 方案来调整和优化系统。当然不同的系统和应用场景有不同的优化方案,tuned-adm 预先配置的优化策略不是总能满足要求,这时候就需要定制,tuned-adm 允许用户自己创建和定制新的调优方案。

系统的性能优化是个很大的话题,如果对这方面感兴趣可以参考 Linux 性能监测系列文章:
介绍CPUMemory, IO, Network, Tools.

安装和启动 tuned:

# yum update
# yum install tuned

# service tuned start
# chkconfig tuned on

# service ktune start
# chkconfig ktune on

查看当前优化方案:

# tuned-adm active
Current active profile: default
Service tuned: enabled, running
Service ktune: enabled, running

查看预先配置好的优化方案:

# tuned-adm list
Available profiles:
- laptop-battery-powersave
- virtual-guest
- desktop-powersave
- sap
- server-powersave
- virtual-host
- throughput-performance
- enterprise-storage
- laptop-ac-powersave
- latency-performance
- spindown-disk
- default
Current active profile: default

如果服务器是虚拟机母机的话,可以选用 virtual-host 方案优化。如果报错 “kernel.sched_migration_cost” is an unknown key 可以通过编辑 sysctl.ktune 这个文件解决。

# tuned-adm profile virtual-host
Reverting to saved sysctl settings:                        [  OK  ]
Calling '/etc/ktune.d/tunedadm.sh stop':                   [  OK  ]
Reverting to cfq elevator: sda sdb sdc sdd sde sdf sdg     [  OK  ]
Stopping tuned:                                            [  OK  ]
Switching to profile 'virtual-host'
Applying deadline elevator: sda sdb sdc sdd sde sdf sdg    [  OK  ]
Applying ktune sysctl settings:
/etc/ktune.d/tunedadm.conf:                                [FAILED]
  error: "kernel.sched_migration_cost" is an unknown key

Calling '/etc/ktune.d/tunedadm.sh start':                  [  OK  ]
Applying sysctl settings from /etc/sysctl.conf
Starting tuned:                                            [  OK  ]

# vi /etc/tune-profiles/virtual-host/sysctl.ktune
...
#kernel.sched_migration_cost = 5000000
...

# tuned-adm profile virtual-host

如果是企业存储服务器的话,可以用 enterprise-storage 方案:

# tuned-adm profile enterprise-storage
Stopping tuned:                                            [  OK  ]
Switching to profile 'enterprise-storage'
Applying deadline elevator: dm-0 sda sdb sdc sdd           [  OK  ]
Applying ktune sysctl settings:
/etc/ktune.d/tunedadm.conf:                                [  OK  ]
Calling '/etc/ktune.d/tunedadm.sh start':                  [  OK  ]
Applying sysctl settings from /etc/sysctl.conf
Starting tuned:                                            [  OK  ]

上面预定的方案不是总能满足要求,如果有自己的需求可以定制自己的方案。自己定制很容易,切换到优化方案的配置目录,拷贝一个例子,然后编辑里面的相关参数就可以了,使用 tuned-adm list 命令会看到刚创建的新方案 my-virtual-host:

# cd /etc/tune-profiles/
# cp -r virtual-host my-virtual-host
# vi my-virtual-host/*

# tuned-adm list
Available profiles:
- laptop-battery-powersave
- virtual-guest
- desktop-powersave
- sap
- server-powersave
- virtual-host
- throughput-performance
- enterprise-storage
- laptop-ac-powersave
- latency-performance
- spindown-disk
- default
- my-virtual-host
Current active profile: virtual-host

Linux 性能监测:工具

一个完整运行的 Linux 系统包括很多子系统(介绍CPUMemoryIONetwork,…),监测和评估这些子系统是性能监测的一部分。我们往往需要宏观的看整个系统状态,也需要微观的看每个子系统的运行情况。幸运的是,我们不必重复造轮子,监控这些子系统都有相应的工具可用,这些经过时间考验、随 Unix 成长起来、简单而优雅的小工具是我们日常 Unix/Linux 工作不可缺少的部分。

下面这张图片很好的总结了 Linux 各个子系统以及监控这些子系统所需要的工具,如果你对 Linux 系统管理(sysadmin & devops)感兴趣、想入门的话,可以从这张图开始慢慢了解和熟悉各个工具。对于熟练的 Linux 屌丝,这张图你应该能问答自如。(图片来自:Linux Performance Analysis and Tools,幻灯片也很精彩,建议对照阅读。)

linux performance analysis and tools

Linux 性能监测:介绍
Linux 性能监测:CPU
Linux 性能监测:Memory
Linux 性能监测:IO
Linux 性能监测:Network

用 Google Docs 监控网站是否在线

监控服务器、VPS 的工具和服务有很多,比如开源工具就有 Nagios, Cacti, Zabbix, Zenoss, Ganglia, … 如果自己不想 host 这些监控软件的话,可以考虑外包给第三方服务,比如 Pingdom, ServerDensity, ScoutApp, PagerDuty 等都做的很棒。如果自己要求不多、只是想监控一下网站(而不是整个服务器的各个性能指标的话)可以考虑一些免费监控服务,比如 monitor.us, SiteUptime, Montastic, site24x7 … 这里介绍的是完全不同的另类办法,用 Google Docs 来监控网站,还包括免费的手机报警功能哦~

点击 这里 会新建一个页面询问是否要拷贝一个文档:

Google Docs

Make a new copy of this document?
This copy will appear in your document list.

Yes, make a copy.

选择 Yes, make a copy. 后就会在自己的 Google Docs 里面生成一个名为 Copy of Website Monitor 的文件,按照提示填写要监控的Wbsite URLs,监控报警用的 Email Address,短信提示 SMS Notifications 就可以了。

Website URLs ::
Email Address ::
SMS Notifications ::
Help ::

填写完后再运行菜单上的 Website Monitor 的 Step1: Initialize 和 Step2: Start,不用了的话就 Uninstall (Stop). 默认的监控频率是每5分钟检查网站一次。

using google docs monitoring website uptime

如果对背后的代码有兴趣的话,可以看看原文 Website Monitor with Google Docs.

Pinboard 的 PHP/MySQL 架构

Pinboard 是一个提供在线书签服务的网站,和 Delicious 类似,不同的是 Pinboard 不是免费的,而且是从一开始就收费——采用有趣的渐进式收费,也就是说每增加一个人、后来的人就需多付0.001美元(按照 number of users * 0.001 的公式),这样的收费方式利用了人们的 “趁便宜赶快买,明天会更贵” 的心理,提供了一套独特的收费模式。让 VPSee 惊讶的是他们背后的技术出奇的简单,没有 Fotolog 那种 MySQL 集群+Memcached 集群,也没有 Netlog 那么复杂的数据库切分。在他们的 About 页面上,这位来自罗马利亚的创始人说:

Pinboard is written in PHP and Perl. The site uses MySQL for data storage, Sphinx for search, and Amazon S3 to store backups. There is absolutely nothing interesting about the Pinboard architecture or implementation; I consider that a feature!

数据

1亿6千多万个书签
5200多万个标签
9400多万个 urls
989 GB 的数据

平台

MySQL
PHP
Perl
Ubuntu
APC
Sphinx
Cron jobs
Amazon S3

硬件

服务器 1:64 GB, 主数据库(master),用来存储用户数据和搜索;
服务器 2:32 GB, 备用主数据库(failover master),用来爬 feeds 等一些后台任务
服务器 3:16 GB, web 服务器和从数据库(slave)
另外提一下,他们租用的这三台服务器有两台是从 DigitalOne 租用的,还有一台是从 ServerBeach 租的。

pingboard arch

架构

  • 他们运行的是 Ubuntu 操作系统;
  • 每台服务器上(一共3台)均保留一份整体数据库的拷贝;
  • 网站运行在 16GB 的服务器上,数据库完全放在内存里,页面装载时间提高了10倍;
  • 采用 master-master 数据库架构加上一个只读的 slave,所有写操作都在一个数据库上进行,第二个 master 数据库服务器主要用来计算,比如统计全局链接数,用户统计等;每天晚上数据库用 mysqldump 备份,然后备份的数据以压缩的形式储存在 Amazon S3 上。
  • Perl 脚本用来运行后台任务,比如下载 feeds、缓存页面、处理 email、生成 tag 云标签、备份数据等。他们选择 Perl 的理由是因为自己很熟悉而且有大量的库可以使用。像 “最受欢迎的书签” 这样的功能一般都是在晚上里通过后台的定时任务(cron job)完成。PHP 用来生成 HTML 页面,没有使用任何 templating engine,也没有使用任何框架(framework)。APC 用来做 PHP 缓存,没有用其他缓存技术,Sphinx 用来做搜索引擎。

经验

  • 使用成熟、老掉牙的技术,这样保证网站和程序运行快而且不会因为软件 bug 丢失数据。(VPSee 非常赞同这点,使用简单和可以理解的技术,我们相信技术是拿来用的,不是拿来炫的。)
  • 保持小规模会有趣得多,当你自己亲自提供客服支持和与客户打交道的时候你会发现很有价值;
  • 服务器成本用每 GB 内存(或存储)的价格来衡量,Pinboard 最初使用的是 Linode 和 Slicehost 的 VPS,后来发现 VPS 不够用,随着内存增大 VPS 越来越贵,价格不如独立服务器。(按照 VPSee 的个人经验,低端(<= 4GB)用 VPS 划算、高端(>=16GB)用独立服务器划算。)
  • 按照服务划分服务器,比如 web 服务器就拿来做 web 服务器,最好不要拿来干别的。

Bloglines 的技术选择和经验

VPSee 以前常用 Bloglines 的 RSS 阅读器订阅一些博客,后来改成 Google Reader 用了一段时间,再后来干脆直接在 Mac 上装个 NetNewWire 客户端,并且可以和 Google Reader 同步,非常方便阅读和管理。这篇文章介绍了 Bloglines 创始人 Mark Fletcher 的的一些创业经验、技术选择和架构等,值得学习学习,特别是对一边工作一边创业的小团队来说。

Bloglines 是典型的车库文化,Mark Fletcher 当初是一边干着正式的工作一边开始自己的创业的,硅谷有很多 startup(创业公司)都是这样起步的,这是包括著名高科技风险投资公司 Y Combinator 创始人 Paul Graham 在内的很多创业大师都推荐的创业方式,在确定自己的创业/赚钱想法可行之前保持稳定的收入来源,这样有助于减少创业的风险和压力,毕竟不是每个人都是 Bill Gates,不是每个人都可以放弃大学或工作开始创业并取得成功的。让人惊奇的是,Bloglines 2005年卖给 Ask.com 的时候还不到10个人。遗憾的是,Ask.com 决定将在今年的10月1日关闭 Blogline.

创业经验

  • 激情,因为这辈子大部分时间都会花在工作和事业上,如果对自己所做的事情没有兴趣和激情的话是不可能坚持到最后的;
  • 采用廉价的技术,现在是互联网创业的好时候,硬件和软件(开源)越来越便宜;
  • Keep it simple,保持简单,使用简单的技术并让为用户觉得简单;(把简单的事情做好就是不简单
  • 夜晚工作,使用自己晚上或者周末的时间工作在自己的创业项目上,从亲朋好友那里寻找资金,免费的服务=更少的压力,免费服务 down 几个小时不会有人抱怨;
  • 雇佣一个律师
  • Web services API 是个好东西
  • 寻找帮助(尤其需要找个好的系统管理员)
  • 考虑外包(eLance.com)

软件选择

  • DBJ (http://cr.yp.to), qmail, djbdns, daemontools
  • ClearSilver (web templating package)
  • Berkeley DBs
  • Linux/Apache
  • C/C++/Bash/Python
  • Skiplist data structure(一个数据结构算法)
  • 避免使用 NFS
  • 避免在 MySQL 中使用表级别的锁,因为不 scale

硬件选择

  • 是租用独立服务器还是托管呢?Bloglines 选择了租用,起步的费用更少;
  • 一切为廉价硬件设计,Google 就是个用廉价硬件搭建服务器集群的好例子;
  • eBay 是个买便宜硬件的好地方;
  • APC PDUs;
  • HP ProCurve 很不错;
  • 避免使用 Seagate Ultra-SCSI 硬盘;
  • 一个有好的 ssh 客户端的手机,这样可以在任何地方 ssh 到服务器上。

存储选择

  • 关系数据库 vs. 文件,他们的所有博客文章都采用文件方式存储;
  • RAID vs. Redundant,他们在所有机器上都保留博客文章副本,如果一台机器 down 了不影响访问;
  • Linux software RAID 1,非常稳定。

系统管理

  • 网站服务器采用 DNS round robin,不必设置负载均衡;
  • 采用热备份冷处理,每小时备份,但是到线下再处理数据(比如 RSS 的订阅数可以每天线下统计,不必即时统计);
  • 小心服务器温度,如果硬盘出问题,可能是服务器过热、温度不适造成的。

监测 Linux 进程的实时 IO 情况

作为系统管理员和 VPS 服务商,经常会碰到服务器或者 VPS 磁盘 IO 繁忙的时候,VPSee 通常都会用一些工具来检测,其中一个常用的工具就是自己写的 iotop 脚本,可以很方便看到哪个进程在频繁 IO. 上周五收到一位网友的邮件和留言,问到这篇文章:如何查看进程 IO 读写情况?里的 WRITE 为什么会出现是 0 的情况,这是个好问题,VPSee 在这里好好解释一下。首先看看我们怎么样才能实时监测不同进程的 IO 活动状况。

block_dump

Linux 内核里提供了一个 block_dump 参数用来把 block 读写(WRITE/READ)状况 dump 到日志里,这样可以通过 dmesg 命令来查看,具体操作步骤是:

# sysctl vm.block_dump=1
or
# echo 1 > /proc/sys/vm/block_dump

然后就可以通过 dmesg 就可以观察到各个进程 IO 活动的状况了:

# dmesg -c
kjournald(542): WRITE block 222528 on dm-0
kjournald(542): WRITE block 222552 on dm-0
bash(18498): dirtied inode 5892488 (ld-linux-x86-64.so.2) on dm-0
bash(18498): dirtied inode 5892482 (ld-2.5.so) on dm-0
dmesg(18498): dirtied inode 11262038 (ld.so.cache) on dm-0
dmesg(18498): dirtied inode 5892496 (libc.so.6) on dm-0
dmesg(18498): dirtied inode 5892489 (libc-2.5.so) on dm-0

问题

一位细心的网友提到这样一个问题:为什么会有 WRITE block 0 的情况出现呢?VPSee 跟踪了一段时间,发现确实有 WRITE 0 的情况出现,比如:

# dmesg -c
...
pdflush(23123): WRITE block 0 on sdb1
pdflush(23123): WRITE block 16 on sdb1
pdflush(23123): WRITE block 104 on sdb1
pdflush(23123): WRITE block 40884480 on sdb1
...

答案

原来我们把 WRITE block 0,WRITE block 16, WRITE block 104 这里面包含的数字理解错了,这些数字不是代表写了多少 blocks,是代表写到哪个 block,为了寻找真相,VPSee 追到 Linux 2.6.18 内核代码里,在 ll_rw_blk.c 里找到了答案:

$ vi linux-2.6.18/block/ll_rw_blk.c

void submit_bio(int rw, struct bio *bio)
{
        int count = bio_sectors(bio);

        BIO_BUG_ON(!bio->bi_size);
        BIO_BUG_ON(!bio->bi_io_vec);
        bio->bi_rw |= rw;
        if (rw & WRITE)
                count_vm_events(PGPGOUT, count);
        else
                count_vm_events(PGPGIN, count);

        if (unlikely(block_dump)) {
                char b[BDEVNAME_SIZE];
                printk(KERN_DEBUG "%s(%d): %s block %Lu on %s\n",
                        current->comm, current->pid,
                        (rw & WRITE) ? "WRITE" : "READ",
                        (unsigned long long)bio->bi_sector,
                        bdevname(bio->bi_bdev,b));
        }

        generic_make_request(bio);
}

很明显从上面代码可以看出 WRITE block 0 on sdb1,这里的 0 是 bio->bi_sector,是写到哪个 sector,不是 WRITE 了多少 blocks 的意思。还有,如果 block 设备被分成多个区的话,这个 bi_sector(sector number)是从这个分区开始计数,比如 block 0 on sdb1 就是 sdb1 分区上的第0个 sector 开始。

Linux 下用 smartd 监测硬盘状况

和处理器、内存比较,硬盘是服务器上最慢的子系统、是最容易出现性能瓶颈的地方,也是最脆弱的部分。因为硬盘离处理器距离最远而且访问硬盘要涉及到一些机械操作,比如转轴、寻轨等,而机械是容易出故障的。作为 VPS 服务商和系统管理员来说,最害怕的就是硬盘出毛病,所以监测硬盘的健康状况、提前预警是件很重要的事情。我们 PC 服务器上差不多1.5年都会有硬盘坏掉,坏掉前一点征兆都没有,SUN 服务器上的情况要好得到,很多 SATA/SCSI 硬盘运行了5年都没问题,看样子品牌服务器还是贵得有理由的。VPSee 前段时间看过 Google 发表的一篇论文:Failure Trends in a Large Disk Drive Population 也证实了我们的经历,结论是所有坏掉的硬盘中只有60%可以被 S.M.A.R.T. 检测到,也就是说 S.M.A.R.T. 的测试结果只有60%是正确的,所以我们还不能完全依赖 S.M.A.R.T. 的监测结果。

目前市面上所有的硬盘都具有 S.M.A.R.T. (Self-Monitoring, Analysis and Reporting Technology) 特性,smartmontools 就是利用这一特性监测硬盘的软件包,包含 smartctl 和 smartd 两个程序,前者是前台命令行工具、后者是后台运行程序,smartmontools 不是 Linux 的专利,也支持 BSD, Solaris 等系统。

安装 smartmontools

在 CentOS 5.x 下安装:

# yum install kernel-utils

在 CentOS 6.x/Fedora 下安装:

# yum install smartmontools

在 Debian/Ubuntu 下安装:

# apt-get install smartmontools

使用 smartmontools

在使用 smartmontools 测试之前先检查一下硬盘是否具有 SMART 特性:

# smartctl -i /dev/sda

=== START OF INFORMATION SECTION ===
Device Model:     SEAGATE ST32500NSSUN250G 0741B58YP8
Serial Number:    5QE58YP8
Firmware Version: 3.AZK
User Capacity:    250,056,000,000 bytes
Device is:        Not in smartctl database [for details use: -P showall]
ATA Version is:   7
ATA Standard is:  Exact ATA specification draft version not indicated
Local Time is:    Thu Jul 22 22:39:07 2010 SAST
SMART support is: Available - device has SMART capability.
SMART support is: Enabled

如果上面 SMART support 是 Disabled 状态的话,需要开启 SMART 的支持:

# smartctl -s on /dev/sda

=== START OF ENABLE/DISABLE COMMANDS SECTION ===
SMART Enabled.

检查硬盘状况,如果下面的结果不是 PASSED 的话你需要立刻警觉起来,马上备份所有数据,硬盘随时都可能出问题(不过值得注意的是就算结果是 PASSED 并不意味着硬盘100%就安全,PASS 不能代表没问题,没 PASS 代表一定有问题):

# smartctl -H /dev/sda

=== START OF READ SMART DATA SECTION ===
SMART overall-health self-assessment test result: PASSED

做个快速自检:

# smartctl -t short /dev/sda

=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===
Sending command: "Execute SMART Short self-test routine immediately in off-line mode".
Drive command "Execute SMART Short self-test routine immediately in off-line mode" successful.
Testing has begun.
Please wait 1 minutes for test to complete.
Test will complete after Thu Jul 22 22:51:00 2010

Use smartctl -X to abort test.

执行上面的自检命令后等待一段时间,可以通过下面命令来看进度和结果:

# smartctl -l selftest /dev/sda

=== START OF READ SMART DATA SECTION ===
SMART Self-test log structure revision number 1
Num  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error
# 1  Short offline       Completed without error       00%     20949         -
# 2  Short offline       Completed without error       00%     20947         -

要做长时间自检的话(很耗时,建议放在凌晨时间段做):

# smartctl -t long /dev/sda

查看出错日志:

# smartctl -l error /dev/sda

=== START OF READ SMART DATA SECTION ===
SMART Error Log Version: 1
No Errors Logged

配置 smartmontools

在 CentOS/Fedora 下:

# vi /etc/smartd.conf
# /etc/init.d/smartd restart

在 Debian/Ubuntu 下:

# vi /etc/default/smartmontools
# vi /etc/smartd.conf
# /etc/init.d/smartmontools restart

可以通过修改以上的 smartmontools 的配置文件来定期对硬盘做健康检查,就像给人定期体检一样,体检过了并不代表就没病(很多疾病用体检的设备都查不到),所以这也符合 Google 的硬盘报告所说的情况,所有坏掉的硬盘中只有60%可以被 S.M.A.R.T. 检测到(所有生病的人中只有60%能在体检的时候发现)。

Linux 多核下绑定进程到不同 CPU(CPU Affinity)

上个星期介绍了在 Linux 多核下如何绑定硬件中断到不同 CPU,其实也可以用类似的做法把进程手动分配到特定的 CPU 上,平时在 Linux 上运行的各种进程都是由 Linux 内核统一分配和管理的,由进程调度算法来决定哪个进程可以开始使用 CPU、哪个进程需要睡眠或等待、哪个进程运行在哪个 CPU 上等。如果你对操作系统的内核和进程调度程序感兴趣的话,不妨看看那本经典的 Operating Systems Design and Implementation(Linus Torvalds 就是看了这本书受到启发写出了 Linux),从简单的 Minix 入手,hack 内核是件很有意思的事情,VPSee 以前修改过 Minix 内核的进程调度,学到了内核方面的很多东西。另外推荐一本课外读物:Just for Fun,Linus Torvalds 写的一本自传。

Linux 给我们提供了方便的工具用来手动分配进程到不同的 CPU 上(CPU Affinity),这样我们可以按照服务器和应用的特性来安排特定的进程到特定的 CPU 上,比如 Oracle 要消耗大量 CPU 和 I/O 资源,如果我们能分配 Oracle 进程到某个或多个 CPU 上并由这些 CPU 专门处理 Oracle 的话会毫无疑问的提高应用程序的响应和性能。还有一些特殊情况是必须绑定应用程序到某个 CPU 上的,比如某个软件的授权是单 CPU 的,如果想运行在多 CPU 机器上的话就必须限制这个软件到某一个 CPU 上。

安装 schedutils

在 CentOS/Fedora 下安装 schedutils:

# yum install schedutils

在 Debian/Ubuntu 下安装 schedutils:

# apt-get install schedutils

如果正在使用 CentOS/Fedora/Debian/Ubuntu 的最新版本的话,schedutils/util-linux 这个软件包可能已经装上了。

计算 CPU Affinity 和计算 SMP IRQ Affinity 差不多:

0x00000001    (CPU0)
0x00000002    (CPU1)
0x00000003    (CPU0+CPU1)
0x00000004    (CPU2)
...

使用 schedutils

如果想设置进程号(PID)为 12212 的进程到 CPU0 上的话:

# taskset 0x00000001 -p 12212

计算 SMP IRQ Affinity

前天我们讨论了如何绑定特定的硬件中断到特定的 CPU 上,分散和平衡各个中断到不同的 CPU 上以获取更大性能的处理能力。上篇限于篇幅的关系,没有来得及进一步说明 “echo 2 > /proc/irq/90/smp_affinity” 中的 ”2“ 是怎么来的,这其实是个二进制数字,代表 00000010,00000001 代表 CPU0 的话,00000010 就代表 CPU1, “echo 2 > /proc/irq/90/smp_affinity” 的意思就是说把 90 中断绑定到 00000010(CPU1)上。所以各个 CPU 用二进制和十六进制表示就是:

               Binary       Hex 
    CPU 0    00000001         1 
    CPU 1    00000010         2
    CPU 2    00000100         4
    CPU 3    00001000         8

如果我想把 IRQ 绑定到 CPU2 上就是 00000100=4:

# echo "4" > /proc/irq/90/smp_affinity

如果我想把 IRQ 同时平衡到 CPU0 和 CPU2 上就是 00000001+00000100=00000101=5

# echo "5" > /proc/irq/90/smp_affinity

需要注意的是,在手动绑定 IRQ 到 CPU 之前需要先停掉 irqbalance 这个服务,irqbalance 是个服务进程、是用来自动绑定和平衡 IRQ 的:

# /etc/init.d/irqbalance stop

还有一个限制就是,IO-APIC 有两种工作模式:logic 和 physical,在 logic 模式下 IO-APIC 可以同时分布同一种 IO 中断到8颗 CPU (core) 上(受到 bitmask 寄存器的限制,因为 bitmask 只有8位长。);在 physical 模式下不能同时分布同一中断到不同 CPU 上,比如,不能让 eth0 中断同时由 CPU0 和 CPU1 处理,这个时候只能定位 eth0 到 CPU0、eth1 到 CPU1,也就是说 eth0 中断不能像 logic 模式那样可以同时由多个 CPU 处理。