![什么是屏蔽模式?](https://linux22.com/image/141537/%E4%BB%80%E4%B9%88%E6%98%AF%E5%B1%8F%E8%94%BD%E6%A8%A1%E5%BC%8F%EF%BC%9F.png)
据我了解,在 GNU/Linux 中,文件权限也称为文件的模式并且术语“掩码”至少可以表示以下不同的含义:
- 这掩码shell内置(通常的意思)。
- 这掩码shell内置的相应系统调用。
- 这掩码shell内置的相应命令
umask
。 - shell 过程值也称为文件创建掩码, 也位掩码要不就面具。
- 一个特定于用户的文件创建掩码,影响该用户独有的进程(然后它称为用户掩码→ 用户的文件创建掩码)。
这掩码外壳内置
一个可以使用掩码umask
通过使用适当的参数执行命令来构建 shell :
通过这样做,我们设置了一个面具对于当前的shell进程树;
要么针对当前shell进程树中的所有用户,要么只针对我们自己的用户;
然而,一般来说,任何此类更改都会继承到新流程,可能是另一个外壳)。
数理逻辑基础
我明白那个数理逻辑包括操作连词又名安定( ∧
) 的基础是掩码外壳内置。因此:
一组操作数的 and 为真,当且仅当,它的所有操作数都为 true
我进一步了解有一个同名的按位运算基于这个逻辑。 Anding 与数字相加 ( x + y → z
) 或字符串连接 ( )不同x alongside y → xy
。
我的问题
我知道可以这样“屏蔽一种模式”:
OCTAL BINARY HUMAN-READABLE
0666 0110110110 -rw-rw-rw-
∧ 0555 0101101101 -r-xr-xr-x
0444 0100100100 -r--r--r--
但我不确定这是否正确。
我的问题
什么是屏蔽模式(以及如何实现0666 ∧ 0555 → 0444
)?
答案1
umask
、shell 命令和umask
、函数,都设置文件创建掩码,也称为umask
.
你已经将其改写为
A
umask
表示 shell 内置命令和基于该命令并包含通常称为变量的 shell 函数文件创建掩码其值为位掩码要不就面具。
这在很多方面都是不正确的:
- 该
umask
函数不是 shell 函数;请参阅上面的链接; - 该函数不包含变量;它设置当前进程的文件创建掩码;
- 所依据的价值不仅仅是通常提到的作为“文件创建掩码”,它是文件创建掩码(其值不称为“位掩码”或“掩码”)。
A面具影响当前进程树中的一些实用程序,包括可以更改的其他 shell(因此 shell Y 不一定具有 shell X 的掩码)。
口罩一般不会产生任何影响。文件创建掩码影响当前进程并被继承全部新创建的子进程。子进程可以自由地再次更改它自己。
此文件创建掩码作用于新创建文件的权限。文件权限,也称为文件模式,是一组 12 位编码文件所有者、组和其他用户的访问权限;看这个规范的答案了解详情。它们通常表示为四位或三位八进制值。他们不是比特流。
新创建的文件的权限要么由创建给定文件的程序指定,要么默认指定(IE由它们用来创建文件的函数指定)。前者的示例包括使用以下命令创建文件(或目录)的程序open
或者creat
或者mkdir
,必须明确指定他们想要的模式。后者的例子包括使用的程序fopen
,其中文件以默认 0666 模式结束。当前umask
值屏蔽此模式。
你将其改写为
这在很多方面都是不正确的:
- 在创建文件之前,而不是之后,将掩码应用于请求的模式;
mkdir
(这里是一个函数,不是一个实用程序,但这同样适用于同名的实用程序)不是忽略文件创建掩码。
umask
考虑到 时,生成的模式是将 umask 作为位掩码应用于请求模式的结果:所请求模式中设置的每个位都会根据 中的相应位进行检查,umask
并且仅在后者未设置时才保留。就二进制运算而言,请求的模式与 的补码进行按位与umask
。因此,umask
模式为 0666 的 0022 会得到 0644;不是通过减法,而是因为 0666 和 0755(0022 的补码)是 0644。同样,umask
模式为 0666 的 0011 的结果是 0666。
让我们更详细地看看计算过程。它通常表示为减法,包括在您链接到的答案中,但重要的是要了解它不是;umask
用作面膜。因此应用值 0022:
Octal Binary
Mode 0666 000110110110
Mask 0022 000000010010 Bits set here mask bits above
Result 0644 000110100100
Octal Binary
Mode 0644 000110100100
Mask 0022 000000010010
Result 0644 000110100100
这通常是通过将模式与掩码的补码进行按位与来计算的:
Octal Binary
Mask 0022 000000010010
Compl. 7755 111111101101
Mode 0666 000110110110
Result 0644 000110100100
chmod
应用在其命令行上指定的模式而不umask
考虑。其他工具也可以这样做,即使在创建文件时也是如此。因此cp
和tar
,当指示保留权限时,将复制权限或恢复权限而不考虑umask
。
这个答案更详细的内容。
你的最后问题是
我的理解够准确吗?怎么会是0666∧0555→0444?
第一个问题的答案显然是否定的。第二个问题的答案是因为这就是按位和的工作原理。将操作数重写为二进制:
Octal Binary
0666 000110110110
0555 000101101101
现在对每个位位置执行按位与。这意味着取每个垂直对齐的位对,以及它们(在上面的示例中,0 ∧ 0 三次,然后 1 ∧ 1, 1 ∧ 0, 0 ∧ 1, 1 ∧ 1 等):
000100100100
(0 ∧ 0 为 0,0 ∧ 1 为 0,1 ∧ 0 为 0,1 ∧ 1 为 1)。将上面的内容转换回八进制,最终得到 0444。
答案2
模式是什么
术语“文件模式”是指 Linux 系统上可用的标准文件权限(不考虑访问控制列表,这是一个不同的品种)。
文件的模式由 12 位组成,每个位代表一个可以授予或不授予的权限(因此一位足以表明这一点)。
例如,权限“文件可以被组成员读取”是从右边的第6位。
为了便于使用,这 12 位被分为 4 组,每组 3 位。 3 位二进制数可以采用 8 个不同的值,这与八进制数字 (0–7) 可以表示的值数量完全相同。
因此,这 12 个权限可以表示为 0-7777 范围内的 4 位八进制数。
更容易让人困惑的是,通常用附加的前导零来表示八进制数(就像按照0x
惯例以十六进制数为前缀一样),因此众数为 0–07777。
为了更简单:在大多数情况下,您只会对低九位感兴趣,因此从这里开始我将重点关注 0–0777。
为什么要写成八进制
为什么使用八进制?它使阅读模式变得更容易!
模式的最低九位代表以下权限位,以该顺序。我将不使用二进制表示,而是以八进制显示相应位的值(从chmod
(2) 复制):
00400 read by owner
00200 write by owner
00100 execute/search by owner
00040 read by group
00020 write by group
00010 execute/search by group
00004 read by others
00002 write by others
00001 execute/search by others
看到图案了吗?1
总是表示执行/搜索,2
总是写入,并且4
总是读取。如果允许读取和执行,但不允许写入,则始终为数字5
,所有 3 个权限读/写/执行一起为始终7
。为了进行比较,请查看十进制值:
Allow read/execute for others: 0005, decimal 5.
Allow read/execute for group: 0050, decimal 40.
Allow read/execute for owner: 0500, decimal 320.
Allow read/execute for owner and group: 0550, decimal 360.
Allow read/execute for all, write
only for owner: 0755, decimal 493.
因此八进制使其更加一致:数字的位置是所有者/组/其他,并且数字告诉您有关三个读/写/执行位的所有信息。
umask 是什么
umask 是一个进程的属性(即,一个正在运行的程序,例如您的 shell),每个进程都有一个。它确定该进程时不设置的权限创建一个新文件。外壳命令umask
设置 shell 的掩码。什么时候这shell 启动另一个程序,然后该程序从调用 shell 继承 umask。因此,在一个 shell 中设置 umask 将不是影响其他程序,除非它们是第一个贝壳的后代并被创造后设置 umask。这就是为什么 umask 应该在会话的早期由脚本设置。
不管其他人怎么说,使用077
;-)
当有新文件时已创建,通过程序,程序将所需的权限传递给open
(2)系统调用。操作系统删除 umask 中设置的位,并将结果用于创建文件。您可以使用以下 C 程序来对此进行测试:
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <err.h>
#include <stdio.h>
int main(int argc, char **argv) {
// check for enough command line arguments
if (argc < 3)
errx(1, "Usage: %s <filename> <octalmode>", argv[0]);
// parse 2nd argument as octal integer
char *endptr = NULL;
int mode = (int)strtol(argv[2], &endptr, 8);
if (!*argv[2] || *endptr || mode < 0)
errx(2, "Not an octal mode: %s", argv[2]);
// create new file with given mode
int fd = open(
argv[1],
O_WRONLY|O_CREAT|O_EXCL,
mode
);
if (fd < 0)
err(1, "Failed to create file %s", argv[1]);
printf("open(\"%s\", ..., 0%03o) successful\n", argv[1], mode);
close(fd);
return 0;
}
编译:
$ gcc -o mkfile mkfile.c
按照这个例子:
$ umask 77 # set umask to 0077
$ umask # check umask
0077
$ rm -f foo # delete old to make sure a new file will be created
$ ./mkfile foo 660 # create file `foo` with mode 0660
open("foo", ..., 0660) successful
$ ls -l foo
-rw------- 1 sk users 0 Nov 6 12:09 foo
注意程序如何请求权限 rw-rw----,即模式 0660,但组的权限被 umask 完全剥夺。
umask: 0077 000 000 111 111
umask bitwise negated: 07700 111 111 000 000
open's argument: 0660 000 110 110 000
(open's argument) AND (NEG umask) 0600 000 110 000 000
一般来说,程序应该建议在最宽松的情况下它认为有用的权限,并将权限的剥离留给操作系统的 umask。因此,使用(2)创建目录时使用0777 mkdir
,使用(2)创建普通文件时使用0666 open
。仅当有意义时才进行偏离,例如,加密工具可以使用open
0600 来存储其私钥,并且编译器可以用于0755
它创建的可执行二进制文件。在所有这些情况下,umask 会在实际创建文件时从文件中删除不需要的权限。
下面是编译器尝试创建一个每个人都可读和可执行的文件的示例,但只能由用户(模式 0755)在 umask 077 的设置中写入:
$ rm -f foo
$ umask 77
$ ./mkfile foo 0755
open("foo", ..., 0755) successful
$ ls -l foo
-rwx------ 1 sk users 0 Nov 6 12:15 foo
在 umask 0 的设置中(允许程序请求的所有位):
$ rm -f foo
$ umask 0
$ ./mkfile foo 0755
open("foo", ..., 0755) successful
$ ls -l foo
-rwxr-xr-x 1 sk users 0 Nov 6 12:16 foo
实际上,gcc
甚至会请求模式0777:
$ umask 0
$ rm -f mkfile
$ gcc -o mkfile mkfile.c
$ ls -l mkfile
-rwxrwxrwx 1 sk users 17k Nov 6 12:19 mkfile
所以不要使用 umask 0。
答案3
在Linux中,默认文件权限为0644,默认目录权限为0755,默认umask为0022。
现在,由于文件的完全权限是 0666,因此默认权限来自 (0666 - 0022 = 0644),目录的默认权限是 (0777 - 0022 = 0755)。
您可以使用 设置掩码#umask 0000
,它将创建具有完整 666/777 权限的文件和目录(但这非常不安全)。
答案4
我无法理解 GNU/Linux 中的 umask 是什么
好的。
以及用 anding 计算它。
我给了你这个公式:
mode=$(printf "%04o\n" "$(( (8#$default) & (~(8#$umask)) ))")
使用 default=0666 和 umask=0022 你会得到:
$ printf "%04o\n" "$(( (8#0666) & (~(8#0022)) ))"
0644
在 Linux 中,umask 既意味着 shell 内置命令,也意味着更改系统值的内核函数,通常称为文件创建掩码,也称为位掩码或只是掩码,由内置命令通过参数调用。
应写为:
在linux中,umask是shell内置函数的名称、内核函数的名称和进程值的名称。内置函数和函数都可以更改过程值。
- 它不是系统值。每个进程都有一个 umask,该 umask 会被复制到其子进程。
- 过程值不是通常命名为文件创建掩码, 它是这文件创建掩码。
- 它不称为位掩码或掩码。
掩码会影响当前进程树中的一些子进程,包括可以更改它的其他 shell(因此 shell Y 不一定具有 shell X 的掩码)。
这掩码影响定义的进程以及从该进程启动的子进程。
- 每个孩子都可以改变自己的掩码。
文件权限,也称为文件模式,是一组 12 个二进制位,编码文件的用户、组和其他用户对该文件的访问权限(ugo → bbbbbbbbbbbb 的流)。
文件模式是一个数字(12个二进制数字或4个八进制数字或3个十六进制数字)
$ bc <<<'ibase=8; mask=1644; obase=2; mask; obase=8; mask; obase=16; mask'
1110100100
1644
4A8
然而,文件权限通常表示为四到三位八进制值(例如 - 0644 或 644)。
模式是一个带有 3 的数字或者四位数。
就像123
和0123
一样是十进制数。
数学逻辑包括合取运算,又称“与”(∧),当“一组操作数的与为真当且仅当其所有操作数为真时”时发生。基于该逻辑有一个同名的按位运算。
好的。
Anding 与数字相加 (x + y → z) 或字符串串联 (x 与 y → xy) 不同。
好的。
设置不带或带 umask 的模式(通过其掩码)
模式始终使用 umask 设置。
一些实用程序(例如 mkdir)会创建具有独立模式的文件,而不使用 umask(因此这些文件的模式不会被屏蔽)。
不,umask 始终有效。
其他一些实用程序创建具有某些“屏蔽”权限的文件(即,权限是由屏蔽产生的)。例如,实用程序使用 fopen() 函数创建文件,其中首先识别掩码,然后使用基于它的权限创建文件。
该模式是以下结果:
mode=$(printf "%04o\n" "$(( (8#$default) & (~(8#$umask)) ))")
屏蔽模式是通过按位与完成的,结果如下:
模式是与默认值进行和运算的结果否定的掩码。
OCTAL BINARY HUMAN-READABLE
umask 0222 000010010010 --w--w--w-
not-umask 7555 111101101101 N/A
default ∧ 0666 000110110110 -rw-rw-rw-
result 0444 000100100100 -r--r--r--
我的理解够准确吗?怎么会是0666∧0555→0444?
有几个问题需要改进,只有 anding(不带否定)是:
0666 → 0 011 011 011
0555 → 0 101 101 101
如果你匹配垂直这些二进制数字,遵循以下规则: - 如果它们相等,则在下面写另一个相同的数字 - 如果它们不同,则在下面写一个零。
0666 → 0 110 110 110
0555 → 0 101 101 101
0 100 100 100
0 4 4 4
0444 → 0 100 100 100