2019-10-28
位运算基础
位运算,就是直接对二进制位进行与、或、非等逻辑运算。
位运算并不仅限于布尔类型的数据。Int类型数据在内存中也是以二进制数据进行存储的,位计算可以直接对整数在内存中的二进制位进行操作。举个例子,7的二进制是111,6的二进制是110,直接进行与运算“7&6”,相当于二进制进行与运算“111&110”。逐位进行与运算,运算结果110,转化为十进制是6,因此运算结果7&6=6。所有的编程语言都提供了位运算符,你可以用不同的语言编写上述计算,结果都一致。
位运算可以用于权限管理,每一个二进制位来表示是否拥有某个权限。Linux中的文件权限就是用位计算实现的,需要控制读、写、执行3个权限,仅需用3位二进制数来表示:
二进制 | 十进制 | 权限 |
读 写 执行 | ||
0 0 0 | 0 | 无权限 |
0 0 1 | 1 | 只可执行 |
0 1 0 | 2 | 只可写 |
0 1 1 | 3 | 可写可执行 |
1 0 0 | 4 | 只可读 |
1 0 1 | 5 | 可读可执行 |
1 1 0 | 6 | 可读可写 |
0 0 0 | 7 | 可读可写可执行 |
下文将以此为例子,介绍位计算权限控制的原理。
权限管理的实现
校验权限:与运算
把需要校验的权限数值和当前的权限数值进行与运算,用来判断是否拥有某个权限。如果运算结果是被校验的权限值,则说明有这个权限;如果运算结果是0,则说明没有权限。
举个例子,写入的权限是2(010),判断权限6(110)有没有写入权限:
二进制:110 & 010 = 010 十进制:6 & 2 = 2
返回结果是2,说明权限6包含了写入的权限2。
再判断权限4(100)有没有写入权限:
二进制:100 & 010 = 000 十进制:4 & 2 = 0
返回结果是0,说明权限4不包含写入权限2。
添加权限:或运算
把需要添加的权限数值和当前的权限数值进行或运算,可以添加权限。
举个例子,给只读的权限4(100)增加写入2(010)权限:
二进制:100 | 010 = 110 十进制:4 | 2 = 6
运算的结果已经变成可读可写6了。
如果对原本已经有的权限进行或运算也没关系,比如可以给可读可写的权限6(110)增加写入权限2(010):
二进制:110 | 010 = 110 十进制:6 | 2 = 6
原本的权限不会受到任何影响。
去除权限:非运算
把需要去除的权限数值和当前的权限数值进行或运算,可以去除权限。
举个例子,把可读可写的权限6(110)去除写入2(010)权限:
二进制:110 ^ 010 = 100 十进制:6 ^ 2 = 4
运算的结果已经变成只读4了。
不能对原本就没有的权限进行非运算。
总结
位运算实现的权限控制,具有运算速度快、节省存储空间、兼容所有的编程语言等优点,在软件系统架构中经常使用。
位运算也有一些局限性。随着权限数量的增加,数据长度变长,可读性会下降。受限于储存和运算位数限制,权限数存在上限,比如32位操作系统的权限就不能多于32个。
本文未经许可禁止转载,如需转载请联系 JAY@oonne.com