cpu調用進程或線程的方式:
Linux內核的進程調度器根據自有的調度策略將系統中的一個進程調度到某個CPU上執行。一個進程在前一個執行時間是在cpuM上運行,而在后一個執行時間則是在cpuN上運行,這樣的情況在cpu中是很可能發生的,因為linux對進程執行的調度采用時間片法則,而在默認情況下,一個普通的進程或線程的處理器親和性提現在所有可用的CPU上,進程或線程有可能在這些cpu之中的任何一個上執行。
進程的處理器親和性(Processor Affinity),即cpu綁定設置,是指將進程綁定到特定的一個或多個cpu上去執行,而不允許將進程調度到其他cpu上。Linux內核對進程的調度算法也是遵守進程的處理器親和性設置的。設置進程的處理器親和性帶來的好處是可以減少進程在多個cpu之間交換運行帶來的緩存命中失效(cache missing),從該進程運行的角度來看,可能帶來一定程度上性能的提升。
換個角度來看,對進程親和性的設置也可能會導致整個系統的進程調度變得低效。特別是在多處理器、多核、多線程技術使用的場景,如果不能對CPU、內存等有深入的了解,對進程的處理器親和性進行設置可能導致系統的整體性能的下降而非提升。
kvm虛擬機設置CPU親和性
每個虛擬機的vcpu在宿主機上,都表現為一個普通的qemu線程,可以使用taskset工具對其進行設置處理親和性,使其綁定到某一個或幾個固定的cpu上去調度。盡管Linux內核的進程調度算法已經非常高效了,在多數情況下是不需要對進程的調度進行干預,不過,在虛擬化環境中,有時有必要將客戶機的qemu進程或線程綁定到固定的cpu上執行。
實例:
系統:centos 7.2 x64 logical CPU number in total:4
要求:創建2vcpu虛擬機,將每個vcpu綁定到固定的cpu上

cpu綁定邏輯圖
# 查看邏輯cpu個數 [root@kvm ~]# cat /proc/cpuinfo| grep "processor"| wc -l 4
將邏輯cpu 2、3 隔離
[root@kvm ~]# vim /etc/default/grub GRUB_TIMEOUT=5 GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)" GRUB_DEFAULT=saved GRUB_DISABLE_SUBMENU=true GRUB_TERMINAL_OUTPUT="console" GRUB_CMDLINE_LINUX="ipv6.disable=1 isolcpus=2,3 crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet" GRUB_DISABLE_RECOVERY="true" # 添加如下: ipv6.disable=1 # 禁止ipv6 isolcpus=2,3 # 隔離2、3號邏輯cpu [root@kvm ~]# grub2-mkconfig -o /boot/grub2/grub.cfg # 重新生成grub配置文件 Generating grub configuration file ... Found linux image: /boot/vmlinuz-3.10.0-327.el7.x86_64 Found initrd image: /boot/initramfs-3.10.0-327.el7.x86_64.img Found linux image: /boot/vmlinuz-0-rescue-42369fb880724a588225bd22cf55ab04 Found initrd image: /boot/initramfs-0-rescue-42369fb880724a588225bd22cf55ab04.img done [root@kvm ~]# reboot # 修改后重啟生效
# 查看每個cpu的進程數
[root@kvm ~]# ps -eLo psr | grep 0 | wc -l 311 [root@kvm ~]# ps -eLo psr | grep 1 | wc -l 58 [root@kvm ~]# ps -eLo psr | grep 2 | wc -l 5 [root@kvm ~]# ps -eLo psr | grep 3 | wc -l 5 # 通過以上信息,邏輯cpu2,3已經隔離成功。通過top命令查看可以發現2、3空閑為100%
# 創建虛擬機
[root@kvm ~]# qemu-kvm -name 'test1' -cpu host -smp 2 -m 512m -drive file=/opt/iso/cirros-0.3.4-i386-disk.img,if=virtio,media=disk -nographic -name: 虛擬機的名字,注意不是主機名 -cpu: cpu的類型,host 表示使用物理機的cpu類型 -smp: 使用cpu核心數 -m: 內存數量 -drive: 設置磁盤使用選項; file:磁盤所在目錄 if:使用類型,virtio表示半虛擬化 media:磁盤類型,這里磁盤就是disk、cd就是cdrom # 查看代表vcpu的QEMU線程 [root@kvm ~]# ps -eLo ruser,pid,ppid,lwp,psr,args | grep qemu-kvm | grep -v grep root 2347 2287 2347 1 qemu-kvm -name test1 -cpu host -smp 2 -m 512m -drive file=/opt/iso/cirros-0.3.4-i386-disk.img,if=virtio,media=disk -nographic root 2347 2287 2351 0 qemu-kvm -name test1 -cpu host -smp 2 -m 512m -drive file=/opt/iso/cirros-0.3.4-i386-disk.img,if=virtio,media=disk -nographic root 2347 2287 2352 1 qemu-kvm -name test1 -cpu host -smp 2 -m 512m -drive file=/opt/iso/cirros-0.3.4-i386-disk.img,if=virtio,media=disk -nographic
# 綁定代表整個客戶機的QEMU進程,使其運行在邏輯cpu2上
[root@kvm ~]# taskset -cp 2 2347 pid 2347's current affinity list: 0,1
pid 2347's new affinity list: 2
# 綁定第一個vcpu的線程,使其運行在邏輯cpu2上
[root@kvm ~]# taskset -cp 2 2351 pid 2351's current affinity list: 0,1
pid 2351's new affinity list: 2
# 綁定第二個vcpu的線程,使其運行在邏輯cpu3上
[root@kvm ~]# taskset -cp 3 2352 pid 2352's current affinity list: 0,1
pid 2352's new affinity list: 3
# 查看QEMU 線程的綁定是否生效。第5列為處理器親和性
[root@kvm ~]# ps -eLo ruser,pid,ppid,lwp,psr,args | grep qemu-kvm | grep -v grep root 2347 2287 2347 2 qemu-kvm -name test1 -cpu host -smp 2 -m 512m -drive file=/opt/iso/cirros-0.3.4-i386-disk.img,if=virtio,media=disk -nographic root 2347 2287 2351 2 qemu-kvm -name test1 -cpu host -smp 2 -m 512m -drive file=/opt/iso/cirros-0.3.4-i386-disk.img,if=virtio,media=disk -nographic root 2347 2287 2352 3 qemu-kvm -name test1 -cpu host -smp 2 -m 512m -drive file=/opt/iso/cirros-0.3.4-i386-disk.img,if=virtio,media=disk -nographic
# 執行vcpu綁定后查看邏輯cpu2上運行的線程
[root@kvm ~]# ps -eLo ruser,pid,ppid,lwp,psr,args | awk '{if($5==2) print $0}' root 272 2 272 2 [watchdog/2] root 273 2 273 2 [migration/2] root 274 2 274 2 [ksoftirqd/2] root 275 2 275 2 [kworker/2:0] root 276 2 276 2 [kworker/2:0H] root 2347 2287 2347 2 qemu-kvm -name test1 -cpu host -smp 2 -m 512m -drive file=/opt/iso/cirros-0.3.4-i386-disk.img,if=virtio,media=disk -nographic root 2347 2287 2351 2 qemu-kvm -name test1 -cpu host -smp 2 -m 512m -drive file=/opt/iso/cirros-0.3.4-i386-disk.img,if=virtio,media=disk -nographic
# 執行vcpu綁定后查看邏輯cpu3上運行的線程
[root@kvm ~]# ps -eLo ruser,pid,ppid,lwp,psr,args | awk '{if($5==3) print $0}' root 277 2 277 3 [watchdog/3] root 278 2 278 3 [migration/3] root 279 2 279 3 [ksoftirqd/3] root 280 2 280 3 [kworker/3:0] root 281 2 281 3 [kworker/3:0H] root 2347 2287 2352 3 qemu-kvm -name test1 -cpu host -smp 2 -m 512m -drive file=/opt/iso/cirros-0.3.4-i386-disk.img,if=virtio,media=disk -nographic root 2572 2 2572 3 [kworker/3:1]
通過以上查看,在cpu進行綁定之前,代表這個虛擬機的QEMU進程和代表各個vcpu的QEMU線程分別被調度到cpu0和cpu1上。使用taskset命令將QEMU進程和第一個vcpu的線程綁定到cpu2,將第二個vcpu線程綁定到cpu3上。在綁定之后即可查看到綁定結果生效,代表兩個vcpu的QEMU線程分別運行在cpu2和cpu3上,即使再過一段時間,它們也不會被調度到其他cpu上。
總的來說,在kvm環境中,一般並不推薦手動設置QEMU進程的處理器親和性來綁定vcpu,但是,在非常了解系統硬件架構的基礎上,根據實際應用的需求,可以將其綁定到特定的cpu上,從而提高客戶機中的cpu執行效率或實現cpu資源獨享的隔離性。
