Futex 简述

简介:futex 全称为Fast User-space Mutex,是Linux 2.5.7 内核引入的锁原语,不同于其他进程间通信IPC原语(如信号量Semaphore、信号Signal和各种锁pthread_mutex_lock),futex更轻量级、快速,一般应用开发人员可能很少用到,但可基于futex实现各类读写锁、屏障(barriers)和信号机制等。

相关背景

在Linux的早期版本(内核Linux 2.5.7 版本以前),进程间通信(Inter-Process Communication,IPC)沿用的是传统Unix系统和System V 的IPC,如信号量(Semaphores)和Socket 等,这些IPC 均基于系统调用(System Call)。这类方法的缺点是当系统竞争度较低时,每次都进行系统调用,会造成较大系统开销。

原理和做法

用户程序每次调用IPC机制都会产生系统调用,程序发生用户态和内核态的切换,futex 的基本思想是竞争态总是很少发生的,只有在竞争态才需要进入内核,否则在用户态即可完成。futex的两个目标是:1)尽量避免系统调用;2)避免不必要的上下文切换(导致的TLB失效等)。

具体而言,任务获取一个futex 将发起带锁的减指令,并验证数值结果值是否为0(加上了锁),如果成功则可继续执行程序,失败(为已经占用的锁继续加锁)则任务在内核被阻塞。为相同futex 变量的加锁的任务被阻塞后放在同一个队列,解锁任务通过减少变量(只有一个加锁且锁队列为空)或进入内核从锁队列唤醒任务。

注意:futex 在Linux 的内核实现为一个系统调用(SYS_futex),用户程序如果直接调用它肯定会进入内核态,它还需要和其他语句(如原子操作)配合使用,新手在未理解其futex 原理和并发控制机制时极易犯错,这也是为什么不推荐直接使用它的原因。

继续阅读

安装RTAI5.2 基于Ubuntu18.04和4.14.111 内核

本文记录在我笔记本上安装最新版本RTAI(5.2)的过程和中间遇到的问题及解决方法,虽然不能覆盖所有问题,但希望能给后来者一些帮助。

安装的主要步骤:

1、安装操作系统和工具;

2、给内核打补丁并配置;

3、安装打补丁的内核与RTAI。

步骤一:安装操作系统和工具

1.1 安装操作系统

我选择的是Ubuntu18.04,因为这是带Linux 4.**.***内核的最新Ubuntu 版本(Ubuntu19.04 是以Linux5.**内核开始了)。而RTAI5.2 支持的最新内核版本即为4.14.111;

1.2 安装工具

这些工具是内核编译时需要的,下面命令可以保存为脚本执行

sudo apt install libncurses5-dev

sudo apt install libssl-dev

sudo apt install bison

sudo apt install flex

sudo apt install libssl-dev

sudo apt install libelf-dev

sudo apt install make gcc

sudo apt install patch

sudo apt install unzip

sudo apt install autoconf

注意:如果你使用的是不同的Linux 发布版(Redhat或openSUSE),有些包的名称是不同的,比如对于Redhat,libssl的安装包是libssl-devel。

注意:如果你采用的是Ubuntu16.04,那么可能因为包依赖的原因,你无法用apt install 命令安装libssl1.1,而这个包是在编译4.14.111 内核时必须的,所以建议你要么换更高版本OS,要么在Ubuntu 网站( https://packages.debian.org/stretch/amd64/libssl1.1/download )手动安装该包(sudo dpkg -i libssl1.1_1.1.0k-1~deb9u1_amd64.deb)。

1.3 安装已编译的Linux 内核4.14.111 (可选的)

该步骤是可选的,它会给系统安装上Linux4.14.111 的内核,从而获得一个默认的内核配置文件供后面使用,如果你是第一次安装RTAI,建议你执行该步骤。

在内核网站 https://kernel.ubuntu.com/~kernel-ppa/mainline/v4.14.111/ 下载内核安装包:

cd ~/Downloads/

wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v4.14.111/linux-headers-4.14.111-0414111_4.14.111-0414111.201904052241_all.deb

wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v4.14.111/linux-headers-4.14.111-0414111-lowlatency_4.14.111-0414111.201904052241_amd64.deb

wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v4.14.111/linux-image-unsigned-4.14.111-0414111-lowlatency_4.14.111-0414111.201904052241_amd64.deb`

wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v4.14.111/linux-modules-4.14.111-0414111-lowlatency_4.14.111-0414111.201904052241_amd64.deb

然后使用dpkg -i 命令安装

sudo dpkg -i *.deb   #执行该命令是可能会遇到错,再重新执行该命令可以解决;

sudo update-grub

sudo reboot

重启后可以在Grub (长按shift进入Grub)中看到安装后的内核有“Generic” 和“lowlatency” 两种。如果进入Grub 有困难,在Grub 配置文件(/etc/default/grub)中修改配置`GRUB_TIMEOUT_STYLE=hidden` 为`GRUB_TIMEOUT_STYLE=false`并更新Grub 菜单`sudo update-grub`。

步骤二:内核打补丁和编译

2.1 下载内核 (https://cdn.kernel.org/pub/linux/kernel/v4.x/)

内核的名称为 linux-4.1.111.tar.gz,为之后编译和安装方便,将源码解压到`/usr/src` 中,并创建一个软链接到该源码目录。

cd /usr/src

sudo tar xvf linux-4.1.111.tar.gz

sudo ln -sf linux-4.1.111 linux

然后,从`/boot` 中拷贝配置文件:

cd /usr/src/linux

sudo cp /boot/config-4.14.111-0414111-lowlatency .config

如果你已经有了一个配置文件(比如你安装过老版本RTAI,在其Linux 内核中拷贝其配置文件即可)uIf you already have a configuration file (e.g. in your old RTAI patched Linux system), just copy it to the source path(`/usr/src/linux`).

2.2 给内核打补丁(Ubuntu 的补丁和RTAI 的补丁)

Ubuntu 是Linux 的一个发行版本,并对Linux 内核代码做了少量修改,所以在编译内核前应该打上Ubuntu 的补丁(https://kernel.ubuntu.com/~kernel-ppa/mainline/v4.14.111/)。

cd ~/Downloads/

wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v4.14.111/0001-base-packaging.patch

wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v4.14.111/0002-UBUNTU-SAUCE-add-vmlinux.strip-to-BOOT_TARGETS1-on-p.patch

wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v4.14.111/0003-UBUNTU-SAUCE-tools-hv-lsvmbus-add-manual-page.patch

wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v4.14.111/0004-adhoc-from-__future__-import-syncconfig.patch

wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v4.14.111/0005-UBUNTU-SAUCE-no-up-disable-pie-when-gcc-has-it-enabl.patch

wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v4.14.111/0006-debian-changelog.patch

wget https://kernel.ubuntu.com/~kernel-ppa/mainline/v4.14.111/0007-configs-based-on-Ubuntu-4.14.0-11.13.patch

cd /usr/src/linux

sudo patch -p1 < ~/Downloads/0001-base-packaging.patch

sudo patch -p1 < ~/Downloads/0002-UBUNTU-SAUCE-add-vmlinux.strip-to-BOOT_TARGETS1-on-p.patch

sudo patch -p1 < ~/Downloads/0003-UBUNTU-SAUCE-tools-hv-lsvmbus-add-manual-page.patch

sudo patch -p1 < ~/Downloads/0004-adhoc-from-__future__-import-syncconfig.patch

sudo patch -p1 < ~/Downloads/0005-UBUNTU-SAUCE-no-up-disable-pie-when-gcc-has-it-enabl.patch

sudo patch -p1 < ~/Downloads/0006-debian-changelog.patch

sudo patch -p1 < ~/Downloads/0007-configs-based-on-Ubuntu-4.14.0-11.13.patch

下载RTAI5.2 并给内核打上相应的补丁 :

wget https://www.rtai.org/userfiles/downloads/RTAI/rtai-5.2.tar.bz2

sudo cp rtai-5.2.tar.bz2 /usr/src/

sudo tar xvf rtai-5.2.tar.bz2

sudo ln -sf rtai-5.2 rtai

cd /usr/src/linux

sudo patch -p1 < /usr/src/rtai/base/arch/x86/patches/hal-linux-4.14.111-x86-3.patch

同样方便起见,我们也为rtai 的源码创建了一个软链接。

注意:安装RTAI补丁和PREEMPT-RT补丁的过程是类似的,如果你想安装PREEMPT-RT补丁,它的地址在这里。下载xz或gz格式后的补丁,可以用xz工具解压发现,是一个个编了序号的补丁,通过下面命令逐个应用补丁

patch -p1 -i /path/to/004-patch.x.y.z

也可以通过下面命令应用所有补丁

xzcat /path/to/patch.xz | patch -p1

bzcat /path/to/patch.xz | patch -p1

2.3 配置内核

配置内核主要参考下面的资料:

如果你的配置文件是从其他老的内核里拷贝过来的,首先应执行:

cd /usr/src/linux

sudo make oldconfig

否则直接执行:

sudo make menuconfig

下面是配置项中应修改的部分:

[改为 -rtai] General setup -> Local Version

[改为 None] General setup -> Stack Protector buffer overflow detection

[Enable] Processor type and features -> Interrupt pipeline

[Disable] Power management and ACPI options -> CPU Frequency Scaling

[Disable] Power management and ACPI options -> ACPI Support -> Processor

[Disable] Power management and ACPI options -> CPU Idle -> CPU idle PM support

[Disable] Kernel hacking -> Compile-time checks and compiler options -> Compile the kernel with debug info

[Disable] Kernel hacking -> Tracers

[Disable] Device Drivers -> Microsoft Hyper-V guest support

[Disable] Device Drivers -> Staging drivers -> Data acquisition support (comedi)

在 README.CONF_RMRKS 文件中要求disable `AUDITSYSCALL`,但是我们在选项中没有找到这一项。一个可替代的方法是编辑 `/usr/src/linux/init/Kconfig`文件,找到`AUDITSYSCALL` 如下部分:

config AUDITSYSCALL

    def_bool y

    depends on AUDIT && HAVE_ARCH_AUDITSYSCALL

替换为:

config AUDITSYSCALL

    bool “Enable system-call auditing support”

    depends on AUDIT && HAVE_ARCH_AUDITSYSCALL

    default y if SECURITY_SELINUX

    help

      Enable low-overhead system-call auditing infrastructure that

      can be used independently or with another kernel subsystem,

      such as SELinux.

然后,你就可以在‘General Setup’选项下看到`ADUITSYSCALL`,取消即可。

如果你的主机是多CPU 或多核的,那么 `Processor type and features` 下的SMP 选项要使能(enabled),并且最大CPU 个数(`Maximum numbers of CPUs`)不应小于物理核心个数(即不考虑Hyperthreading)。因此,建议你在BIOS 中取消Hyperthreading。

步骤三:编译安装内核和RTAI

3.1 编译和安装Linux 内核

cd /usr/src/linux

sudo touch REPORTING-BUGS

sudo make -j3

sudo make modules

sudo make modules_install

sudo make install

sudo update-initramfs –c -k 4.14.111-rtai [注意修改这里的版本名称]

sudo update-grub [注意修改/etc/default/grub 启动项为自己的内核]

sudo reboot

从Linux 内核网站下载的4.14.111 版本的源码目录下没有`REPORTING-BUGS`这个文件,可能会导致你在编译的时候遇到`recipe for target ‘kernel_headers’ failed` 的错误,所以我们首先创建了这个文件。

如果一切顺利的的话,你重启后将在Grub 上看到你自己编译的内核选项:ubuntu18.04_4.14.111-rtai 。

3.2 安装RTAI5.2

RTAI 需要autotools 生成链接编译工具:

cd /usr/src/rtai

sudo autoconf

sudo ./configure

接着配置RTAI :

sudo cp ../linux/.config .rtai_config

sudo make menuconfig

将CPU 个数(`number of CPUs`)设置为实际的物理核心个数即可。

sudo make

sudo make install

如果在编译时遇到下面的错误:

make:execup: .//config.guess: Permission denied

make:execup: .//config.sub: Permission denied

手动修改权限后再编译:

chmod 764 ./config.guess

chmod 764 ./config.sub

RTAI 默认的安装路径是`/usr/realtime`,其中`modules`目录下是编译后的模块库, `testSuite` 目录下是RTAI 的测试程序,通过手动加载模块和运行测试程序可以验证RTAI是否安装成功。

cd /usr/realtime/modules

sudo insmod rtai_hal.ko

sudo insmod rtai_sched.ko

sudo insmod rtai_fifos.ko

sudo insmod rtai_sem.ko

sudo insmod rtai_shm.ko

sudo insmod rtai_rtdm.ko

一般来说,负责进程调度的 rtai_sched.ko 模块如果加载后无死机,则安装成功。

可能遇到的问题

最后罗列一些可能遇到的问题:

1 编译内核时, `implicit declaration of function ‘ipipe_root_**_syscalls’ did you mean ‘ipipe_handle_syscall’ ……` 错误

原因:在内核配置里,ipipeline 没有使能(Enable);

2 加载`sudo insmod rtai_hal.ko` 和`sudo insmod rtai_` 后,系统冻死,键盘和鼠标均无响应

可能原因:General setup -> Stack Protector buffer overflow detection 选项默认是`Strong`,应设置为`None`或 `Regular`,更多配置项参考 README.CONF_RMRKS 。

3 不能进入编译Linux内核后的系统,提示`Gave up waiting for root file system device. Common problems:  …… ALERT! UUID=8e478c20-25e4-49c0-…… does not exist. Drop to the shell`.

可能原因:系统无法识别存储设备,注意配置内核时关于存储的驱动(SATA/PATA)要使能,因为我是在U盘中安装的系统,因此U盘相关的驱动也得使能。

4  当准备加载 rtai_hal.ko 模块时,提示`ERROR: Could not insert module rtai_hal.ko: Operation not permitted`错误,系统日志Syslog(`/var/log/syslog`) 提示`RTAI[hal] RTAI configured with less than num online CPUs`。

可能原因:RTAI 配置的CPU 个数比实际CPU 核心数要多,切记不要算上超线程(Hyperthreading)。

以上错误远不能包含所有你在安装RTAI 时遇到的问题,但你还可以借助下面的工具来帮助你的调试。

一些有用的命令和工具

  • Dmesg

dmesg

  • Syslog  

sudo cat /var/logsys

  • Systemctl

   Systemctl -failed   # 查看哪些内核没有被正常加载

  • RTAI 官网和邮件列表

www.rtai.org

  • Dpkg

dpkg –list | grep linux-image

  • mkinitramfs

Vim 常见问题(StackOverflow 高票问题)

如何退出Vim 编辑器?

:点击 Esc 键,然后 :q 退出编辑器(或 :q! 不保存退出编辑器,或:q! 退出编辑器不保存,或 :x 等同于:wq 退出编辑器并保存))。

 

如何快速缩进多行?

:利用 > 命令, >5> 或者  5>>  缩进五行, >% 缩进一个block(需要将光标放在括号上)。

 

如何在Vim 中符号替换为换行符,:%s/,/\n/g 将会插入^@ 字符?

:用/r 代替 /n 。在Vim 中,/r 和 /n 分别插入0X00 和0X0A 字符。

 

Vim 如何高亮搜索?

set nohlsearch 关闭高亮, set hlsearch! 打开高亮。

 

如何设置搜索大小写不敏感?

: /letter\c搜索letter 且大小写不敏感,/letter\C 大小写敏感(默认);或:set ignorecase 设置大小写不敏感。

 

如何复制一行?

yy 复制一行,dd 剪切一行,p  粘贴内容在本行下一行,P 粘贴内容在本行上一行。

 

w !sudo tee % 如何实现sudo (root 权限)保存的功能?

% 表示当前文件,tee 将即输出到% 还输出到屏幕。

 

如何设置Tab 为4 个空格,并自动缩进?

:在vimrc 中添加

filetype plugin indent on
" show existing tab with 4 spaces width
set tabstop=4
" when indenting with '>', use 4 spaces width
set shiftwidth=4
" On pressing tab, insert 4 spaces
set expandtab

 

如何移动到一行的最后?

A 移动到本行最后并进入插入模式或 $ 移动到最后(普通模式,normal mode)

 

如何编辑多个文件?

:使用tabs(Vim7 中引入),:tabe <filepath> 在新tab 中打开文件,:tabn 和 :tabp 在文件之间切换。还可以通过:sp <filepath> 进行分屏,ctrl+w 在屏幕之前切换。

 

remap/map/noremap 命令

remap 是使得映射命令能够递归地映射。系统默认是开启的(建议)。map/noremapd 都是映射命令。:map 和 :noremap 是递归映射(recursive)和非递归映射(no-recursive)。

:map j gg
:map Q j
:noremap W j

j 映射为 ggQ 递归地映射为 gg。 W 将不会映射到 gg 而只会映射到 j ,因为它使用非递归映射。考虑到还有普通模式(normal)可视模式(visual),还有对应的映射命令(:nmap 和 :nnoremap)与 (:vmap 和 :vnoremap)。

 

如何关闭粘贴时的自动缩进?

:set paste 进入插入粘贴模式(显示-- INSERT (paste) --),粘贴后取消 -:set nopast。可以将<F3> 键进行映射,从而快速切换模式::set pastetoggle=<F3>

 

如何使用寄存器(registers)?

:Vim 中寄存器可以用于暂时存储文本、宏命令等,以备后面使用。

:reg a b c 打印出  a b c 寄存器中内容;"a 表示寄存器a,"ayy 复制一行到寄存器a,"ap复制到当前位置;"Ayy 将内容增添在寄存器a;"+ 是一个特殊寄存器指向系统剪切板(clipboard),"+p 将系统剪切板中的内容粘贴到当前位置; "0 – "9 是九个数字寄存器,"0 寄存器保存复制(yank)的内容,"1 – "9 按时间分别保存删除(dd)的内容。

 

如何快速注释多行?

<Ctrl>+v 进入可视块(visual block)模式,选择多行,<Shift>+i 进入插入(insert)模式,在行首加入注释符(//,#),<Esc> 键将在选择的多行前都添加注释符。

 

如何用字符显示空格?

:set listchars=eol:¬,tab:>·,trail:~,extends:>,precedes:<,space:␣

:set list (根据我的经验,不要显示空格,或者空格用点符号更美观  space:·

 

什么是记录(Vim recording)?

q<letter> 开始记录,再次按q 结束记录,并通过@<letter> 回放。它可以记录所有你输入的,比如查找,移动,替换等操作。非常有用。

 

如何删除空白行?

:g/^$/d

 

如何实现全文缩进对齐?

gg=G。 gg 跳到文件开头, = 缩进对其,G 到文件末尾。

 

如何粘贴内容到系统剪切板(clipboard),或者从系统剪切板到Vim 中?

:寄存器 "* 和 "+ 是系统剪切板寄存器,"*yy 或者 "+yy 将复制行到系统剪切板,"*p 和 "+P 粘贴到本行下一行或者上一行。(我更习惯用<shift>+<insert> 粘贴)

 

如何将(Win)dos 中文件行结束转化为Linux 行结束?

dos2unix 是专门处理这个的工具。或者使用替换命令 :%s/^M//g ,或 :set ff=unix 。

 

如何 “重做”(redo) “回退”(undo)?

u 回退,<Ctrl>+r 重做。

 

如何移动屏幕,而不需要移动光标?

zz 移动当前行到屏幕中间,zt 移动当前行到屏幕顶部,zb 移动当前行到屏幕底部。

 

如何删除行而不存在寄存器中?

"_d 删除到“黑洞”寄存器

 

查找下一个

n 查找文件的上一个,N 查找文件中上一个

 

如何设置非贪婪正则表达?

:用.\{-} 代替.* 。

 

如何设置内容超过80 列后提醒?

:在 ~/.vimrc 内添加

highlight OverLength ctermbg=red ctermfg=white guibg=#592929
match OverLength /\%81v.\+/

 

如何复制文件中所有行?

gg"*yG 复制内容到"* 寄存器。

 

如何关闭单个打开的文件缓存(e.g. vim a.txt b.txt 打开后如何关闭一个文件缓存)?

:bd 关闭当前缓冲区,:ls 列出当前所有缓冲区,:bd2 关闭第二个缓冲区。

 

^M 是什么?

:Unix 用 0xA 表示新行,Windows 则用 0xD 0xA^M 显示为 0xD 。

 

如何关闭所有选项页(tabs)?

:qa 退出所有选项,:wqa保存所有选项页并退出。

 

自动补全?

:YouCompleteMe

 

Ubuntu14.04 上安装pygame

因为在一台ubuntu 服务器上跑个pygame 的程序,在ubuntu14.04 上安装pygame 了一天,之前在windows 上安装很顺利,换做ubuntu 上就有点傻傻的。总结来说尽量不要手动下源包,通过configure 和 make install 来安装,因为存在很多依赖(32-bit,64-bit 等)的问题。应该采用正确的安装姿势:

sudo apt-get install python-game

我的过程如下:

在pygame 官网下载了最新(2009年的(⊙﹏⊙)b,因为基于的SDL 从1.2换做2.0版本了,无法做兼容了)的pygame 源码,解压, python setup.py install  安装。

安装后的结果是可以在程序中 import pygame 并使用基本的函数(如pygame.draw.line 等),但如果要使用相关其他模块时,如 import pygame.font 则会出现 font module not found的问题. 我尝试采用 http://stackoverflow.com/a/15368766/1424948 中的方法安装相关的模块:

$ sudo apt-get install python-dev libsdl-image1.2-dev libsdl-mixer1.2-dev  
libsdl-ttf2.0-dev   libsdl1.2-dev libsmpeg-dev python-numpy subversion 
libportmidi-dev ffmpeg libswscale-dev libavformat-dev libavcodec-dev

但是还是会存在  font module not found 的问题,我也尝试使用自动安装pygame的方法来解决:

$ sudo apt-get install python-pygame

但这个问题应该是之前的手动安装已经无法覆盖,而手动的安装依赖问题无法解决。最终我的解决方法是:

  1. sudo python setup.py clean
  2. 删除 python/site-packages 下的pygame 包
  3. sudo apt-get install python-pygame

完成这三步后,一切OK。

 

 

哪些情况会导致"Undefined Reference Error"

“Undefined Reference Error” 是在程序链接(link)时经常遇到的错误,字面意思来说就是没有找到已经定义的引用,在编译器无法找到用户所使用的变量或函数:

一、缺失头文件

例如声明变量 uint64_t tmp,但没有在开头包含 #include<stdint.h>

例如使用 memset() 需要包含头文件 string.h 或 memory.h

二、缺失目标文件或者库文件(.a .o .so …)

编译器查找用户函数,首先会在本文件中的函数中找,然后在系统环境变量定义的目标文件/库(.a .o .so …)文件中找,最后在链接的目标文件/库文件(.a .o .so …)中寻找用户函数;如果没有找到则报”Undefined Reference Error”错

四、库(目标)文件链接顺序有误

库文件的链接顺序是:依赖的库A 放后面,被依赖的库B 放前面。如果A 和B 相互依赖,则使用A B A 或者B A B 的。

例如main 文件中引用func 文件中函数,则编译顺序为main.o func.o

五、C 函数和C++函数引用问题

C++ 程序链接时可以链接C 的库文件,但在.cc(.cpp) 中引用头文件时需要通过extern “C”{ #include “func.h”} 的方式引用该头文件,否则会提示”Undefined Reference Error”

C 程序无法链接C++ 库文件,否则会提示”Undefined Reference Error”,找不到引用C++ 函数的引用

参考:http://blog.csdn.net/aiwoziji13/article/details/7330333

内存拷贝速度(memcpy())和异或速度

内存拷贝(memcpy())和异或(bit-wise XOR)是程序中运行最快的操作之一,其速度受到CPU、内存和编译器(GCC版本)的影响。

内存拷贝memcpy(des, src, len) 则是将长度为len 的数据从地址src 拷贝到地址des 。

按位异或(异或)可以分为几类:

  1. a^b:两个数值的异或。相当于两个寄存器内值在CPU 中计算异或,大多数CPU 中一个时钟周期完成。速度取决于CPU 的频率,频率越高,速度越快。
  2. a^Region:一个数值与一块内存Region 中的每个值异或,结果保存在Region 中,速度相当于顺序访存。
  3. RegionA = RegionA^RegionB:两块内存中对应位置上的值异或。
  4. RegionC = RegionA^RegionB:两块内存中对应位置上的值异或,结果保存在另一块内存中。

四类异或速度依次递减。平常中越到的是第3 种,本文中异或速度也是第3 种。

继续阅读