理解位运算及使用场景

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

最近在看 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 引用 • 1388 回帖 • 277 关注
  • apue
    1 引用 • 7 回帖

相关帖子

欢迎来到这里!

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

注册 关于
请输入回帖内容 ...
  • 88250

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

  • 其他回帖
  • kuuyee 1
    作者

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

  • lixiaoxianer

    还是很不错的呢

  • kuuyee 1
    作者

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

  • 查看全部回帖

推荐标签 标签

  • V2Ray
    1 引用 • 15 回帖 • 1 关注
  • Latke

    Latke 是一款以 JSON 为主的 Java Web 框架。

    71 引用 • 535 回帖 • 790 关注
  • 快应用

    快应用 是基于手机硬件平台的新型应用形态;标准是由主流手机厂商组成的快应用联盟联合制定;快应用标准的诞生将在研发接口、能力接入、开发者服务等层面建设标准平台;以平台化的生态模式对个人开发者和企业开发者全品类开放。

    15 引用 • 127 回帖 • 1 关注
  • JSON

    JSON (JavaScript Object Notation)是一种轻量级的数据交换格式。易于人类阅读和编写。同时也易于机器解析和生成。

    52 引用 • 190 回帖
  • OpenStack

    OpenStack 是一个云操作系统,通过数据中心可控制大型的计算、存储、网络等资源池。所有的管理通过前端界面管理员就可以完成,同样也可以通过 Web 接口让最终用户部署资源。

    10 引用
  • PWA

    PWA(Progressive Web App)是 Google 在 2015 年提出、2016 年 6 月开始推广的项目。它结合了一系列现代 Web 技术,在网页应用中实现和原生应用相近的用户体验。

    14 引用 • 69 回帖 • 159 关注
  • Flume

    Flume 是一套分布式的、可靠的,可用于有效地收集、聚合和搬运大量日志数据的服务架构。

    9 引用 • 6 回帖 • 637 关注
  • uTools

    uTools 是一个极简、插件化、跨平台的现代桌面软件。通过自由选配丰富的插件,打造你得心应手的工具集合。

    6 引用 • 14 回帖
  • Sublime

    Sublime Text 是一款可以用来写代码、写文章的文本编辑器。支持代码高亮、自动完成,还支持通过插件进行扩展。

    10 引用 • 5 回帖
  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    15 引用 • 136 回帖
  • ActiveMQ

    ActiveMQ 是 Apache 旗下的一款开源消息总线系统,它完整实现了 JMS 规范,是一个企业级的消息中间件。

    19 引用 • 13 回帖 • 668 关注
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 486 关注
  • TGIF

    Thank God It's Friday! 感谢老天,总算到星期五啦!

    288 引用 • 4485 回帖 • 663 关注
  • 宕机

    宕机,多指一些网站、游戏、网络应用等服务器一种区别于正常运行的状态,也叫“Down 机”、“当机”或“死机”。宕机状态不仅仅是指服务器“挂掉了”、“死机了”状态,也包括服务器假死、停用、关闭等一些原因而导致出现的不能够正常运行的状态。

    13 引用 • 82 回帖 • 61 关注
  • 强迫症

    强迫症(OCD)属于焦虑障碍的一种类型,是一组以强迫思维和强迫行为为主要临床表现的神经精神疾病,其特点为有意识的强迫和反强迫并存,一些毫无意义、甚至违背自己意愿的想法或冲动反反复复侵入患者的日常生活。

    15 引用 • 161 回帖 • 3 关注
  • JRebel

    JRebel 是一款 Java 虚拟机插件,它使得 Java 程序员能在不进行重部署的情况下,即时看到代码的改变对一个应用程序带来的影响。

    26 引用 • 78 回帖 • 675 关注
  • OAuth

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

    36 引用 • 103 回帖 • 17 关注
  • 域名

    域名(Domain Name),简称域名、网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。

    43 引用 • 208 回帖
  • Love2D

    Love2D 是一个开源的, 跨平台的 2D 游戏引擎。使用纯 Lua 脚本来进行游戏开发。目前支持的平台有 Windows, Mac OS X, Linux, Android 和 iOS。

    14 引用 • 53 回帖 • 538 关注
  • V2EX

    V2EX 是创意工作者们的社区。这里目前汇聚了超过 400,000 名主要来自互联网行业、游戏行业和媒体行业的创意工作者。V2EX 希望能够成为创意工作者们的生活和事业的一部分。

    17 引用 • 236 回帖 • 316 关注
  • Markdown

    Markdown 是一种轻量级标记语言,用户可使用纯文本编辑器来排版文档,最终通过 Markdown 引擎将文档转换为所需格式(比如 HTML、PDF 等)。

    167 引用 • 1520 回帖
  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    728 引用 • 1273 回帖
  • Sym

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

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

    524 引用 • 4601 回帖 • 700 关注
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    107 引用 • 153 回帖 • 2 关注
  • 星云链

    星云链是一个开源公链,业内简单的将其称为区块链上的谷歌。其实它不仅仅是区块链搜索引擎,一个公链的所有功能,它基本都有,比如你可以用它来开发部署你的去中心化的 APP,你可以在上面编写智能合约,发送交易等等。3 分钟快速接入星云链 (NAS) 测试网

    3 引用 • 16 回帖 • 5 关注
  • SpaceVim

    SpaceVim 是一个社区驱动的模块化 vim/neovim 配置集合,以模块的方式组织管理插件以
    及相关配置,为不同的语言开发量身定制了相关的开发模块,该模块提供代码自动补全,
    语法检查、格式化、调试、REPL 等特性。用户仅需载入相关语言的模块即可得到一个开箱
    即用的 Vim-IDE。

    3 引用 • 31 回帖 • 104 关注
  • Bug

    Bug 本意是指臭虫、缺陷、损坏、犯贫、窃听器、小虫等。现在人们把在程序中一些缺陷或问题统称为 bug(漏洞)。

    76 引用 • 1737 回帖 • 3 关注