理解位运算及使用场景

本贴最后更新于 3314 天前,其中的信息可能已经事过景迁

最近在看 APUE,函数 umask 的例子用到了位运算,认为这是个非常适合使用位运算的场景,有必要笔记一下。例子代码基于 golang,因为最近在学习 golang.

位运算

先来看下位运算的定义:程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算说穿了,就是直接对整数在内存中的二进制位进行操作。摘自百度百科

比如,&运算本来是一个逻辑运算符,但整数与整数之间也可以进行&运算。举个例子,6 的二进制是 110,11 的二进制是 1011,那么 6 & 11 的结果就是 2,它是二进制对应位进行逻辑运算的结果(0 表示False1 表示 True,空位都当 0 处理),下面的代码是用 go 实现的:

func base() {
    a := 6		//    0110
    b := 11	//    1011
                //    ----
                // &  0010 => 2
                // |  1111 => 15
                // ^  1101 => 13
                // &^ 0100 => 4
    fmt.Println(a & b)
    fmt.Println(a | b)
    fmt.Println(a ^ b)
    fmt.Println(a &^ b)
}

四个位运算符说明如下:

0110 & 1011	= 0010 AND 都为1。
0110 | 1011 = 1111 OR 至少一个为1。
0110 ^ 1011 = 1101 XOR 只能一个为1。
0110 &^ 1011 = 0100 AND NOT 清除标志位。

应用场景-Umask

只是位运算的话理解起来挺容易的,但是这种位运算有毛用呢?适于用什么场景?下面我用 Unix 系统的 umask 概念来实践下位运算。关于 umask 的概念请参阅 http://linux.vbird.org/linux_basic/0220filemanager.php#umask。简单来讲,Unix 系统对于文件的权限用 9 个权限位来控制:

[-][rwx][r-x][r--]
 1  234  567  890
  • r:可读 4
  • w:可写 2
  • x:可执行 1
  • -:表示此权限被去除

第一位是用来表示是文件还是目录,先不用管它,主要是后面 9 位。我们经常在授权是用的到 644,755 都是用 r,w.x 这三个值相加得出的。为什么值分别是 4,2,1 呢,我们把 go 语言 sys 包中的源码拿出来看看就明白了:

const (
    S_IRUSR = 0x100 //用户可读
    S_IWUSR = 0x80	//用户可写
    S_IXUSR = 0x40	//用户可执行
    S_IRGRP = 0x20	//组可读
    S_IWGRP = 0x10	//组可写
    S_IXGRP = 0x8	//组可执行
    S_IROTH = 0x4	//其它可读
    S_IWOTH = 0x2	//其它可写
    S_IXOTH = 0x1	//其它可执行
)

这是 sys 包中定义的一些常量,我们来打印下这些都是啥玩意

    fmt.Printf("%9b %3d %s\n", S_IRUSR, S_IRUSR, "用户读")
    fmt.Printf("%9b %3d %s\n", S_IWUSR, S_IWUSR, "用户写")
    fmt.Printf("%9b %3d %s\n", S_IXUSR, S_IXUSR, "用户执行")

    fmt.Printf("%9b %3d %s\n", S_IRGRP, S_IRGRP, "组读 *")
    fmt.Printf("%9b %3d %s\n", S_IWGRP, S_IWGRP, "组写 *")
    fmt.Printf("%9b %3d %s\n", S_IXGRP, S_IXGRP, "组执行")

    fmt.Printf("%9b %3d %s\n", S_IROTH, S_IROTH, "其它读 *")
    fmt.Printf("%9b %3d %s\n", S_IWOTH, S_IWOTH, "其它写 *")
    fmt.Printf("%9b %3d %s\n", S_IXOTH, S_IXOTH, "其它执行")

// 输出
100000000 256 用户可读
 10000000 128 用户可写
  1000000  64 用户可执行
   100000  32 组可读 
    10000  16 组可写 
     1000   8 组可执行
      100   4 其它可读 
       10   2 其它可写 
        1   1 其它可执行

看明白了吧,其实就是把九个权限位置分别标志为 1,用二进制可以很清楚的表示权限位,4,2,1 也就是这么来的。那么 umask 的就可以利用这个位运算,代码如下:

	package main

	import (
		"fmt"
		"golang.org/x/sys/unix"
		"os"
	)

	func main() {
		unix.Umask(0)
		_, err := os.Create("foo")
		if err != nil {
			fmt.Println("Create Error")
		}
		unix.Umask(unix.S_IRGRP | unix.S_IWGRP | unix.S_IROTH | unix.S_IWOTH)
		_, err2 := os.Create("bar")

		if err2 != nil {
			fmt.Println("Create Error")
		}
	}
	

上面的代码可以看到,unix.S_IRGRP | unix.S_IWGRP | unix.S_IROTH | unix.S_IWOTH 就利用了位运算,程序先后创建了两个文件 foobar, 创建 bar 文件时,文件初始权限把其它中的可读可写去除了,所以我们用 ls -la foo bar 命令可以看到输出如下:

[vagrant@mydev ~]$ ls -la foo bar
-rw-------. 1 vagrant vagrant 0 Oct 26 02:54 bar
-rw-rw-rw-. 1 vagrant vagrant 0 Oct 26 02:54 foo

再用 9 个权限位的二进制图说明下:

	100000000 256 用户可读
	 10000000 128 用户可写
	  1000000  64 用户可执行
	   100000  32 组可读 *
	    10000  16 组可写 *
	     1000   8 组可执行
	      100   4 其它可读 *
	       10   2 其它可写 *
	        1   1 其它可执行
	---------
	   110110	unix.S_IRGRP | unix.S_IWGRP | unix.S_IROTH | unix.S_IWOTH

umask 四个参数我用型号标出来了,那经过**| 位运算最终结果就是 110110**,言外之意就是 umask 把标志为 1 的权限位去除了。

最后我把权限位二进制打印代码贴出来

  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    497 引用 • 1387 回帖 • 283 关注
  • apue
    1 引用 • 7 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • kuuyee 1
    作者

    @88250 错!我没有强迫症,就是因为这里发文章需要花💸,所以稍微认真了点! 我是🐅座(Emoji 里竟然没有狮子😜)!

  • 其他回帖
  • 88250

    @kuuyee 难道你也是处女座,哈哈~

  • bozong

    666666666666

  • kuuyee 1
    作者

    @88250 改了两次排版,才发现竟然每次扣 5 分 😰

  • 查看全部回帖

推荐标签 标签

  • 服务器

    服务器,也称伺服器,是提供计算服务的设备。由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力。

    125 引用 • 588 回帖
  • QQ

    1999 年 2 月腾讯正式推出“腾讯 QQ”,在线用户由 1999 年的 2 人(马化腾和张志东)到现在已经发展到上亿用户了,在线人数超过一亿,是目前使用最广泛的聊天软件之一。

    45 引用 • 557 回帖 • 67 关注
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    83 引用 • 37 回帖 • 1 关注
  • 小说

    小说是以刻画人物形象为中心,通过完整的故事情节和环境描写来反映社会生活的文学体裁。

    28 引用 • 108 回帖 • 1 关注
  • CloudFoundry

    Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。

    5 引用 • 18 回帖 • 168 关注
  • 正则表达式

    正则表达式(Regular Expression)使用单个字符串来描述、匹配一系列遵循某个句法规则的字符串。

    31 引用 • 94 回帖
  • Flutter

    Flutter 是谷歌的移动 UI 框架,可以快速在 iOS 和 Android 上构建高质量的原生用户界面。 Flutter 可以与现有的代码一起工作,它正在被越来越多的开发者和组织使用,并且 Flutter 是完全免费、开源的。

    39 引用 • 92 回帖
  • JetBrains

    JetBrains 是一家捷克的软件开发公司,该公司位于捷克的布拉格,并在俄国的圣彼得堡及美国麻州波士顿都设有办公室,该公司最为人所熟知的产品是 Java 编程语言开发撰写时所用的集成开发环境:IntelliJ IDEA

    18 引用 • 54 回帖
  • 单点登录

    单点登录(Single Sign On)是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

    9 引用 • 25 回帖
  • 小薇

    小薇是一个用 Java 写的 QQ 聊天机器人 Web 服务,可以用于社群互动。

    由于 Smart QQ 从 2019 年 1 月 1 日起停止服务,所以该项目也已经停止维护了!

    34 引用 • 467 回帖 • 743 关注
  • CSDN

    CSDN (Chinese Software Developer Network) 创立于 1999 年,是中国的 IT 社区和服务平台,为中国的软件开发者和 IT 从业者提供知识传播、职业发展、软件开发等全生命周期服务,满足他们在职业发展中学习及共享知识和信息、建立职业发展社交圈、通过软件开发实现技术商业化等刚性需求。

    14 引用 • 155 回帖
  • Gitea

    Gitea 是一个开源社区驱动的轻量级代码托管解决方案,后端采用 Go 编写,采用 MIT 许可证。

    4 引用 • 16 回帖 • 6 关注
  • DNSPod

    DNSPod 建立于 2006 年 3 月份,是一款免费智能 DNS 产品。 DNSPod 可以为同时有电信、网通、教育网服务器的网站提供智能的解析,让电信用户访问电信的服务器,网通的用户访问网通的服务器,教育网的用户访问教育网的服务器,达到互联互通的效果。

    6 引用 • 26 回帖 • 510 关注
  • gRpc
    11 引用 • 9 回帖 • 73 关注
  • FlowUs

    FlowUs.息流 个人及团队的新一代生产力工具。

    让复杂的信息管理更轻松、自由、充满创意。

    1 引用 • 3 关注
  • LeetCode

    LeetCode(力扣)是一个全球极客挚爱的高质量技术成长平台,想要学习和提升专业能力从这里开始,充足技术干货等你来啃,轻松拿下 Dream Offer!

    209 引用 • 72 回帖
  • 创业

    你比 99% 的人都优秀么?

    84 引用 • 1399 回帖
  • 运维

    互联网运维工作,以服务为中心,以稳定、安全、高效为三个基本点,确保公司的互联网业务能够 7×24 小时为用户提供高质量的服务。

    149 引用 • 257 回帖
  • 尊园地产

    昆明尊园房地产经纪有限公司,即:Kunming Zunyuan Property Agency Company Limited(简称“尊园地产”)于 2007 年 6 月开始筹备,2007 年 8 月 18 日正式成立,注册资本 200 万元,公司性质为股份经纪有限公司,主营业务为:代租、代售、代办产权过户、办理银行按揭、担保、抵押、评估等。

    1 引用 • 22 回帖 • 762 关注
  • Pipe

    Pipe 是一款小而美的开源博客平台。Pipe 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    132 引用 • 1114 回帖 • 124 关注
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 9 关注
  • Sym

    Sym 是一款用 Java 实现的现代化社区(论坛/BBS/社交网络/博客)系统平台。

    下一代的社区系统,为未来而构建

    524 引用 • 4601 回帖 • 699 关注
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 587 关注
  • Facebook

    Facebook 是一个联系朋友的社交工具。大家可以通过它和朋友、同事、同学以及周围的人保持互动交流,分享无限上传的图片,发布链接和视频,更可以增进对朋友的了解。

    4 引用 • 15 回帖 • 453 关注
  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    85 引用 • 165 回帖 • 2 关注
  • CAP

    CAP 指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。

    11 引用 • 5 回帖 • 608 关注
  • Caddy

    Caddy 是一款默认自动启用 HTTPS 的 HTTP/2 Web 服务器。

    12 引用 • 54 回帖 • 164 关注