Skip to content

C语言open函数与umask函数

相关函数:read, write, fcntl, close, link, stat, umask, unlink, fopen

1、open函数简介

头文件:

#include <sys/types.h>    
#include <sys/stat.h>
#include <fcntl.h>

定义函数:

int open(const char * pathname, int flags);
int open(const char * pathname, int flags, mode_t mode);

函数说明:

参数 pathname 指向欲打开的文件路径字符串.

下列是参数flags 所能使用的旗标:

  • O_RDONLY 以只读方式打开文件
  • O_WRONLY 以只写方式打开文件
  • O_RDWR 以可读写方式打开文件.

上述三种旗标是互斥的, 也就是不可同时使用, 但可与下列的旗标利用OR(|)运算符组合.

  • O_CREAT 若欲打开的文件不存在则自动建立该文件.
  • O_EXCL 如果O_CREAT 也被设置, 此指令会去检查文件是否存在. 文件若不存在则建立该文件, 否则将导致打开文件错误. 此外, 若O_CREAT 与O_EXCL 同时设置, 并且欲打开的文件为符号连接, 则会打开文件失败.
  • O_NOCTTY 如果欲打开的文件为终端机设备时, 则不会将该终端机当成进程控制终端机.
  • O_TRUNC 若文件存在并且以可写的方式打开时, 此旗标会令文件长度清为0, 而原来存于该文件的资料也会消失.
  • O_APPEND 当读写文件时会从文件尾开始移动, 也就是所写入的数据会以附加的方式加入到文件后面.
  • O_NONBLOCK 以不可阻断的方式打开文件, 也就是无论有无数据读取或等待, 都会立即返回进程之中.
  • O_NDELAY 同O_NONBLOCK.
  • O_SYNC 以同步的方式打开文件.
  • O_NOFOLLOW 如果参数pathname 所指的文件为一符号连接, 则会令打开文件失败.
  • O_DIRECTORY 如果参数pathname 所指的文件并非为一目录, 则会令打开文件失败。注:此为Linux2. 2 以后特有的旗标, 以避免一些系统安全问题.

参数mode 则有下列数种组合, 只有在建立新文件时才会生效, 此外真正建文件时的权限会受到umask值所影响, 因此该文件权限应该为 (mode-umaks).

  • S_IRWXU 00700 权限, 代表该文件所有者具有可读、可写及可执行的权限.
  • S_IRUSR 或S_IREAD, 00400 权限, 代表该文件所有者具有可读取的权限.
  • S_IWUSR 或S_IWRITE, 00200 权限, 代表该文件所有者具有可写入的权限.
  • S_IXUSR 或S_IEXEC, 00100 权限, 代表该文件所有者具有可执行的权限.
  • S_IRWXG 00070 权限, 代表该文件用户组具有可读、可写及可执行的权限.
  • S_IRGRP 00040 权限, 代表该文件用户组具有可读的权限.
  • S_IWGRP 00020 权限, 代表该文件用户组具有可写入的权限.
  • S_IXGRP 00010 权限, 代表该文件用户组具有可执行的权限.
  • S_IRWXO 00007 权限, 代表其他用户具有可读、可写及可执行的权限.
  • S_IROTH 00004 权限, 代表其他用户具有可读的权限
  • S_IWOTH 00002 权限, 代表其他用户具有可写入的权限.
  • S_IXOTH 00001 权限, 代表其他用户具有可执行的权限.

返回值:若所有欲核查的权限都通过了检查则返回0 值, 表示成功, 只要有一个权限被禁止则返回-1. 错误代码:

  • EEXIST 参数pathname 所指的文件已存在, 却使用了O_CREAT 和O_EXCL 旗标.
  • EACCESS 参数pathname 所指的文件不符合所要求测试的权限.
  • EROFS 欲测试写入权限的文件存在于只读文件系统内.
  • EFAULT 参数pathname 指针超出可存取内存空间.
  • EINVAL 参数mode 不正确.
  • ENAMETOOLONG 参数 pathname 太长.
  • ENOTDIR 参数pathname 不是目录.
  • ENOMEM 核心内存不足.
  • ELOOP 参数pathname 有过多符号连接问题.
  • EIO I/O 存取错误.

附加说明:使用 access()作用户认证方面的判断要特别小心, 例如在access()后再作open()空文件可能会造成系统安全上的问题.

2、open和fopen区别

以可写的方式fopen一个文件时,如果文件不存在则会自动创建,而open一个文件时必须明确O_CREAT才会创建文件,否则文件不存在就出错返回。

3、奇怪的close函数

头文件:#include<unistd.h> 功能:关闭一个已经打开的文件

为何奇怪?它跟open函数是一对,但为何没有在同一个头文件里面。

  • open是打开文件, 但close是关闭任何描述符, 这两个函数并不是一对
  • 瞎编一个理由:饿盆要显示自己的开源,因此与封闭的克肉丝划清了界限

范例

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
main()
{
    int fd, size;
    char s[] = "Linux Programmer!\n", buffer[80];
    fd = open("/tmp/temp", O_WRONLY|O_CREAT);
    write(fd, s, sizeof(s));
    close(fd);
    fd = open("/tmp/temp", O_RDONLY);
    size = read(fd, buffer, sizeof(buffer));
    close(fd);
    printf("%s", buffer);
}
/*
Linux Programmer!
*/

4、umask函数

代码见:D:\Github\Storage\c++\umask\umask_example.cpp

4-1、作用

此函数的主要作用是在创建文件时设置或者屏蔽掉文件的一些权限。一般与open()函数配合使用。

在C语言中,umask函数用于设置进程的文件创建掩码,它可以限制文件的默认权限。文件创建掩码是一个权限掩码,它与文件的默认权限进行按位与运算,从而得到文件的实际权限。

umask函数的作用是屏蔽掉进程创建文件时的某些权限,例如屏蔽掉其他用户的写权限,从而保护文件的安全性。umask函数的返回值是之前的文件创建掩码。

在Linux系统中,每个文件都有一个权限位,用于控制文件的读、写和执行权限。文件的权限位可以通过chmod命令来修改。例如,chmod 644 test.txt命令可以将test.txt文件的权限设置为644,即文件所有者和组用户的读写权限为可读可写,其他用户的权限为只读。

在使用umask函数时,它可以用来限制新创建文件的默认权限。umask函数的参数是一个文件创建掩码,它是一个8位的二进制数,用于限制新创建文件的默认权限。umask函数会将进程的文件创建掩码设置为指定的值,并返回之前的文件创建掩码。新创建文件的权限位会与进程的文件创建掩码进行按位与运算,从而得到文件的实际权限。

例如,如果进程的文件创建掩码为022,表示新创建文件的默认权限为0666 & ~022,即文件所有者和组用户的读写权限为可读可写,其他用户的权限为只读。如果我们调用umask(0022)函数将文件创建掩码设置为0022,那么新创建文件的默认权限就会变为0644,即文件所有者和组用户的读写权限为可读可写,其他用户的权限为只读。

总之,umask函数的作用是限制新创建文件的默认权限,从而保护文件的安全性。

4-2、之前的文件是指什么?

在使用umask函数时,之前的文件创建掩码指的是当前进程的文件创建掩码。每个进程都有一个文件创建掩码,它是一个8位的二进制数,用于限制新创建文件的默认权限。umask函数可以获取当前进程的文件创建掩码,并且可以修改它。

在调用umask函数之前,进程的文件创建掩码是由操作系统设置的默认值。在Linux系统中,通常默认的文件创建掩码是022,它表示新创建的文件的默认权限为0666 & ~022,即文件所有者和组用户的读写权限为可读可写,其他用户的权限为只读。调用umask函数可以修改进程的文件创建掩码,从而影响新创建文件的默认权限。

4-3、如何打印mode_t变量

在C语言中,可以使用printf函数和格式化字符串来打印mode_t类型的变量。mode_t类型是一个无符号整数类型,通常用于表示文件的权限和类型信息。在打印mode_t类型的变量时,可以使用八进制或十六进制的格式化字符串来输出。

4-4、不是直接使用open函数就能设置文件默认权限了吗

是的,你说得没错。在使用open函数创建文件时,可以通过第三个参数来指定文件的权限。例如,open(“test.txt”, O_CREAT | O_WRONLY, 0644)可以创建一个文件test.txt,并将文件权限设置为0644,即文件所有者和组用户的读写权限为可读可写,其他用户的权限为只读。

但是,umask函数的作用不仅仅是限制新创建文件的默认权限,它还可以保护文件的安全性。在实际应用中,我们通常会将文件创建掩码设置为一个较小的值,例如0022,这样可以屏蔽掉其他用户的写权限,从而保护文件的安全性。如果直接使用open函数设置文件权限,那么文件的权限可能会比较宽松,从而存在一定的安全风险。

另外,umask函数还可以在创建目录时限制目录的默认权限。在Linux系统中,目录的权限也非常重要,它可以控制用户对目录的访问权限。如果目录的权限设置不当,可能会导致目录被非法访问或者修改。因此,在创建目录时,我们也需要考虑目录的权限问题。

4-5、文件创建掩码和文件权限是同一个东西吗

文件创建掩码和文件权限不是同一个东西,它们是两个不同的概念。

文件权限是用于控制文件读、写和执行权限的一组标志位,通常用于表示文件所有者、组用户和其他用户的权限。在Linux系统中,文件权限通常用三个八进制数字来表示,例如0644表示文件所有者和组用户的读写权限为可读可写,其他用户的权限为只读。

文件创建掩码是一个8位的二进制数,用于限制新创建文件的默认权限。文件创建掩码与文件权限进行按位与运算,从而得到文件的实际权限。在Linux系统中,文件创建掩码通常用三个八进制数字来表示,例如022表示新创建文件的默认权限为0666 & ~022,即文件所有者和组用户的读写权限为可读可写,其他用户的权限为只读。

文件权限和文件创建掩码都与文件的访问权限有关,但是它们的作用不同。文件权限用于控制文件的实际权限,而文件创建掩码用于限制新创建文件的默认权限。在实际应用中,我们通常会将文件创建掩码设置为一个较小的值,例如0022,这样可以屏蔽掉其他用户的写权限,从而保护文件的安全性。

4-6、文件创建掩码是二进制数,怎么会表示成022?

你说得对,文件创建掩码是一个8位的二进制数,通常用三个八进制数字来表示。我之前的回答有误,抱歉给你带来困惑。

在Linux系统中,文件创建掩码的每一位都对应着一个文件权限位。文件创建掩码的每一位可以取值0或1,表示是否屏蔽对应的文件权限位。例如,文件创建掩码为00000010,表示屏蔽其他用户的写权限。文件创建掩码可以通过umask函数来设置,它会影响新创建文件的默认权限。

在使用umask函数时,文件创建掩码通常用三个八进制数字来表示。这三个数字分别对应着文件所有者、组用户和其他用户的权限位。例如,文件创建掩码为022,表示屏蔽其他用户的写权限,文件所有者和组用户的权限位不受影响。这个文件创建掩码可以用二进制数表示为000010010,其中第一位表示特殊权限位,后面三位表示文件所有者的权限位,中间三位表示组用户的权限位,最后三位表示其他用户的权限位。

总之,文件创建掩码是一个8位的二进制数,它用于限制新创建文件的默认权限。文件创建掩码可以用二进制数或八进制数表示,通常用三个八进制数字来表示。

4-7、个人心得和理解

old_mask = umask(0) 获取当前进程的文件创建掩码。因为umask函数返回值是之前文件的文件创建掩码,而现在则被设置成了0,因此需要umask(old_mask)再设置回来。

需要注意的是,修改当前进程的文件创建掩码会影响新创建文件的默认权限,但不会影响已经存在的文件的权限。如果需要修改已经存在文件的权限,可以使用chmod函数。

4-8、举例说明创建文件后的读写权限

在使用open()建立新文件时,该参数mode并非真正建立文件的权限,而是(mode&~umask)的权限值。例如,在建立文件时指定文件权限为0666,通常umask值默认为022,则该文件的真正权限则为0666&~022=0644,也就是rw-r-r--。 如:D:\Github\Storage\c++\umask\umask_example.c

4-9、如何计算umask值

umask 命令允许你设定文件创建时的缺省模式,对应每一类用户(文件属主、同组用户、其他用户)存在一个相应的umask值中的数字。对于文件来说,这一数字的最 大值分别是6。系统不允许你在创建一个文本文件时就赋予它执行权限,必须在创建后用chmod命令增加这一权限。目录则允许设置执行权限,这样针对目录来说,umask中各个数字最大可以到7。

该命令的一般形式为:

umask nnn

其中nnn为umask置000-777。

让我们来看一些例子。 计算出你的umask值: 可以有几种计算umask值的方法,通过设置umask值,可以为新创建的文件和目录设置缺省权限。下表列出了与权限位相对应的umask值。在计算umask值时,可以针对各类用户分别在这张表中按照所需要的文件/目录创建缺省权限查找对应的umask值。 例如,umask值002 所对应的文件和目录创建缺省权限分别为6 6 4和7 7 5。 还有另外一种计算umask值的方法。我们只要记住umask是从权限中“拿走”相应的位即可。

umask值与权限:

umask值文件目录
067
166
245
344
423
522
601
700

自己理解:其实就是两者加起来等于6或者7,注意文件权限不能是奇数,这时候加起来会是7。

This website is released under the MIT License.