Android重学系列(七):系统源码小知识之umask(0)的意义

2,419 阅读3分钟

一、前言

Linux系统中每个文件都会涉及到3种用户权限,分别是

  1. 文件目录的所有者: u---User
  2. 文件目录的所有者所在的组的用户: g---Group
  3. 其它用户: o---Others
  4. 所有用户: a---all

权限分为读、写、运行,显示出来就是rwx,如果没有该权限会以-表示,如没有写权限表示为r-x

我们一般可以通过命令行执行ls -dl 或者ls -l来查看某一特定文件、目录的权限

二、Linux的文件权限的规则

我们先在命令行执行下面命令,创建一个文件夹

mkdir test_dir

然后查看文件夹的读写权限

ls -dl test_dir
>> drwxr-xr-x  2 army  staff  64  9 13 19:21 **test_dir**

那这里的drwxr-xr-x是什么意思呢?

其实这里是有一个统一规则的,总共10个字符,来表达不同用户对目录能做什么

  1. 第1个字符表示:文件(-)、目录(d),链接(l),块设备(b)...
  2. 其它字符以3个一组rwx来表达对不同用户的限定,读(r)、写(w)、执行(x),如r-x表示可读不可行可执行
  3. 第一组表示文件所有者的rwx
  4. 第二组表示与文件所有者同一组的rwx
  5. 第三组表示不与文件所有者同一组的其他用户的rwx

image.png

值得注意的是,对于目录来说,rwx有着不一样的意义

  1. 读(r)意味着可以查看目录内的内容,即包含文件,没有此权限我们无法通过ls列出目录中的文件
  2. 写(w)意味着我们可以删除或者创建目录内的文件
  3. 可执行(x)意味着我们可以操作此目录,例如cd到此目录进行一些命令操作

三、Linux文件权限的表示

在程序中,rwx用二进制可表示成 111,同理,rw-可表示成110

同时这一组值我们使用八进制就可对结果进行完全表示,如111 = 7

上文说到每个文件都会涉及到3种用户权限,如drwxr-xr-x就是111101101

用八进制表示则是 755

四、umask是什么

在Linux中,默认新建目录的权限是777,即rwxrwxrwx,可读可写可执行

新建文件的权限则是 666,即rw-rw-rw-,可读可写不可执行

但是就像我们上面创建文件夹时一样,事实并不如我们所料,这是为什么呢?

这就是我们要介绍umask的原因。

umask定义成我们修改和创建文件的掩码,即我们系统的默认权限,如文件的默认权限777减去umask设置的掩码,最终得到我们创建文件的权限

例如Linux默认mask为 022,则777-022=755,也就是 rwxr-xr-x,也就是我们前面创建的test_dir的权限

例如我们主动设置mask为0,然后创建文件

**➜umask 0

**➜touch test_file

**➜ls -dl test_file

输出:-rw-rw-rw-  1 army  staff  0  9 13 20:52 test_file

即系统默认权限666-000=666,即rw-rw-rw

值得注意的是,这里的说的相减并不是我们算术上的减法,因为是不涉及借位和进位的 例如 umask=077,我们创建文件系统默认为666

那这里最终得出的文件权限会是 666-077=600宽泛可以理解为每位去做减法,<0时则等于0

那我们应该怎样理解呢,其实可以这样理解: 例如umask=077,转换成二进制则是 000111111,一共9位,当位上等于1(我们这里后6位都为1),则表示要将被操作的位 置为0,即如果被操作为本来就是0,则相当于不用操作,还是0

原始权限:110 110 110
umask : 000 111 111

result   110 000 000

image.png

五、修改文件权限

1. 修改rwx。

通过chmod有两种方式可对权限进行更改

a. 指定八进制

通过 chmod 3位八进制 目录

chmod 666 test_dir3

b.指定增删位

  1. +:增加权限
  2. -:取消权限
  3. =:重置权限

u、g、o、a即我们引言中描述的用户分组

**➜chmod u+x,g-r,o=rwx test_dir3

**➜ls -dl test_dir3             

drwx-w-rwx  2 army  staff  64  9 13 21:13 test_dir3

2.修改所属组

通过chgrp 修改为用户组admin

chgrp admin test2

3.修改所有者

通过chown 修改为所有者 army

chown army test2

总结

我们在Android的init进程的启动源码会发现umask(0)的调用,现在我们明白了,这是赋予我们接下来创建目录或文件的最高权限做的准备,相当于抹去了系统设置的umask掩码

int FirstStageMain(int argc, char** argv) {
    if (REBOOT_BOOTLOADER_ON_PANIC) {
    InstallRebootSignalHandlers();
    }

    boot_clock::time_point start_time = boot_clock::now();

    std::vector<std::pair<std::string, int>> errors;
    #define CHECKCALL(x) \
    if ((x) != 0) errors.emplace_back(#x " failed", errno);

    // Clear the umask.
    umask(0);

    CHECKCALL(clearenv());
    CHECKCALL(setenv("PATH", _PATH_DEFPATH, 1));
    //这里0755可以相似看成755 即rwxr-xr-x
    CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"));
    CHECKCALL(mkdir("/dev/pts", 0755));
    CHECKCALL(mkdir("/dev/socket", 0755));
    CHECKCALL(mkdir("/dev/dm-user", 0755));
}