一、前言
Linux系统中每个文件都会涉及到3种用户权限,分别是
- 文件目录的所有者: u---User
- 文件目录的所有者所在的组的用户: g---Group
- 其它用户: o---Others
- 所有用户: 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个字符表示:文件(-)、目录(d),链接(l),块设备(b)...
- 其它字符以3个一组rwx来表达对不同用户的限定,读(r)、写(w)、执行(x),如r-x表示可读不可行可执行
- 第一组表示文件所有者的rwx
- 第二组表示与文件所有者同一组的rwx
- 第三组表示不与文件所有者同一组的其他用户的rwx
值得注意的是,对于目录来说,rwx有着不一样的意义
- 读(r)意味着可以查看目录内的内容,即包含文件,没有此权限我们无法通过ls列出目录中的文件
- 写(w)意味着我们可以删除或者创建目录内的文件
- 可执行(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
五、修改文件权限
1. 修改rwx。
通过chmod有两种方式可对权限进行更改
a. 指定八进制
通过 chmod 3位八进制 目录
chmod 666 test_dir3
b.指定增删位
+:增加权限-:取消权限=:重置权限
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));
}