【文档翻译】QNX Neutrino RTOS 7.1用户手册 - 第五章 文件操作

本文翻译自BlackBerry官方提供的QNX® Neutrino® RTOS User's Guide,仅供学习参考使用

第五章 文件操作

文章目录

在QNX Neutrino 系统中,几乎一切都是文件。设备、数据甚至服务通常都用文件来表示。这让你可以轻松地从本地或者远程通过命令行或程序来对文件进行操作。

  • 本章聚焦在防断电文件系统(fs-qnx6.so)中文件的相关操作。防断电文件系统是QNX Neutrino RTOS系统中的默认文件系统。更多信息请参考文件系统操作章节

文件类型

QNX Neutrino 支持多种文件类型。文件类型能让你大致了解文件包含什么类型的数据,以及你应预期文件会如何表现。

ls -l 指令中,如下括号中的字符代表了文件类型:
常规(-)

一个包含了用户数据的文件,例如C代码、HTML、数据。例如:

bash 复制代码
/home/fred/myprog.c

目录(d)

一个目录下包含了文件和其他目录,例如:

bash 复制代码
/home/fred

符号链接(l)

文件或目录的别名,例如,/usr/bin/more是/usr/bin/less的符号链接。更多信息,请参考文件系统操作章节中的"链接与索引"。
特殊命名(n)

其他类型文件的行为和内容不适用于特殊用途文件。例如,/proc/dumper 表示应用程序崩溃时生成核心转储(core dump)的钩子,/dev/random 表示随机数的来源。
字符特殊文件(c)

代表字符设备的条目。例如:/dev/ser1 代表一个串口

**FIFO特殊文件(p)

代表两个程序间通讯的命名管线。例如:PipeA
块特殊文件(b)

代表块设备(如磁盘)的条目。例如,/dev/hd0代表你的基础硬盘驱动的原始数据块
Socket 文件(s)

代表通讯socket的条目,特别是Unix域的socket。更多信息请参考QNX Neutrino C库指南中的socket()接口

一些文件在系统一次启动时会一直存在,例如觉大多是文件和磁盘文件系统。其他文件只存在于管理它们的程序正在运行时。例如内存共享对象、/proc 文件系统中的对象,以及磁盘上仍在被访问的临时文件,尽管指向这些文件的链接(即它们的文件名)已被删除。

文件名和路径名

要访问任何文件或目录,你需要提供一个路径名------这是一个符号名称,用于告诉程序该文件在从根目录 / 派生出的目录树中的具体位置。

一个典型的QNX Neutrino路径名看起来如下:

/home/fred/.profile

在这个例子中,.profile可以在fred目录下被找到,而fred 又在home目录下,home又在/即根目录下:

和Linux与其他Unix类似操作系统一样,QNX Neutrinol路径元素是以斜杠(/)来分隔的。而不是像Microsoft系统中用反斜杠(\)来分隔的。

  • 使用ls指令来浏览你系统中的文件和目录。这个指令和MS-MOS中的dir是一样的。更多信息请参考使用命令行章节的基础目录部分。或命令指南中的ls部分
绝对路径和相对路径

有两种路径类型:
绝对路径

以斜杠(/)开头的路径名。他是相对根目录的,例如,/home/fred/my_apps/favs.
相对路径

不以斜杠(/)开头的路径名,代表了相对你当前工作目录的位置。

例如你当前的目录是/home/fred,一个 相对路径my_apps/favs和绝对路径/home/fred/my_apps/favs是等价的

你不能通过路径名判断它是一个目录、一个文件、一个符号链接还是其他文件类型。判断文件类型需要通过file指令或ls -ld指令。

但一个特例是如果一个路径名以/结尾,它永远代表一个目录。如果你在ls指令上使用-F选项,它会在目录名后显示/。

点和点点目录

大多数目录包含两个特殊链接,.(点)和...(点点)
.(点)

当前目录
...(点点)

当前目录所在的目录(即其父目录)。

因此,例如你要列出你当前工作目录上一层目录的所有内容,你可以输入:

bash 复制代码
ls ..

如果你当前目录是/home/fred/my_apps/favs,你可以输入:

bash 复制代码
ls ../../../..

来列出根目录下所有内容

然后绝对路径(/)更加简洁,你也不用数你需要多少个"点点"

没有硬盘字母

和Microsoft Windows中用路径前的字母(例如C:\)代表硬盘不同,QNX Neutrino 用路径中的常规目录代表硬盘驱动。访问另一文件系统的目录被称为挂载点,例如在第二块硬盘上的分区。

一般基础的基于此判断文件系统是被挂在到/(根目录)。一个完整的QNX Neutrino 将所有其他测盘路径自动挂在/fs路径下,例如:

因此,在基于DOS的系统中,你或许可以通过D:\访问你硬盘的第二分区,而在QNX Neutrino系统中,你或许需要通过/fs/hd0-qnx6-2来访问防断电文件系统第二分区。

更多关于QNX Neutrino系统中典型的路径名的信息,请参考本章中"所有内容的存储位置"。更多关于挂在文件系统的内容,请参考文件系统操作章节。

以点开头的路径名

当你使用ls指令列举目录下的内容是,以英文句号(.)开头的目录通常会被隐藏。程序通常会在配置文件或目录名称前加上一个英文句号,以将其隐藏起来。这些文件(并不令人以外地)被称之为隐藏文件。

除了被ls和一些其他程序特殊处理外,这些隐藏文件并没有什么特别的。使用ls -a可以列出包括隐藏文件的所有文件。

扩展名

文件名扩这(文件名后的.xx)用于告知程序和用户该文件包含的数据类型。

在QNX Neutrino文件系统中,扩展名只是文件名普通的一部分,只要文件名在505 字节的大小限制内,扩展名可以是任何长度。

大多数时候,文件扩展名只是简单的命名规范,但有些工具会根据文件扩展名来决定其行为。QNX Neutrino系统中常见的扩展名列表请参考"文件扩展名"一节

路径空间映射

你可能已经注意到我们之前说到的文件和目录是显示在它的父目录下而不是说父目录包含了这些文件。这是因为QNX Neutrino系统中,路径空间是虚拟的,这是因为在 QNX Neutrino 中,路径名空间是虚拟的------它不仅由挂载在根目录下的介质上的文件系统决定,还由进程管理器所注册的路径及路径别名共同决定。

例如,我们拿路径名空间中的一小部分来看。

在一个典型的基于磁盘的QNX Neutrino系统中,目录 / 映射到物理硬盘分区上文件系统的根目录。而这个文件系统并不真的包含/dev目录,这个目录是通过进程管理器的接管而虚拟存在的。而后文件名ser1也不是真实存在的,它是由串口驱动接管的。

因此,可以创建虚拟路径组合(即组合文件系统)。这种情况发生在多个资源管理器接管路径空间中同一目录下的文件时。

哪个资源管理器管理管理哪个文件或目录是基于路径名映射以及底层文件系统挂在顺序,这在《系统架构指南》进程管理器章节称作"路径名管理"。

  • 组合中文件系统越多,事情就会变得越复杂。从创建可维护的系统的角度,我们建议你越少创建目录组合约好。
文件名规则

QNX Neutrino 支持多种文件系统,每种文件系统对合法文件名有不同的能力和规则。

关于文件系统的能力,请参考文件系统操作章节,关于文件系统的限制,请参考理解系统限制章节。

文件名的最大长度是视文件系统而定的。文件名中的字符可以是除了以下特例以外的任何值(以下均以十六进制表示)

0x00 到 0x1F (全部控制字符)

0x2F (/)

0x7F (擦除)

0xFF

如果你正在使用 Unicode 字符的 UTF-8 表示形式来表示国际字符,那么文件名的长度限制会变得更低,取决于你所用到的文字的扩展范围。

在防断电文件系统文件系统中,你可以通过 UTF-8对Unicode 字符进行编码来使用国际字符。包含UTF-8的字符在命令行中一般无法正确显示。

你也可以用ISO-Latin1补充包和PC上的字符包来表示国际字符。但是这些8-bit字符的显示是由你终端的显示设置决定的。其他操作系统通过网络访问时,它们可能和你预期的显示不同。

包括Microsoft Windows在内的大部分其他操作系统支持UTF-8/Unicode字符。实际上,老版本的Microsoft Windows中的文件名可能使用了多语言的代码页来编码8-bit字符。QNX Neutrino系统中的DOS文件系统可以翻译这些UTF-8表达,但是你需要通过命令行告诉文件系统使用哪个代码页。

所有内容的存储位置

QNX Neutrino 操作系统并不规定具体的文件系统层级分布,系统设计者一般可以自由地组织文件以适用系统的目标。

例如,依据传统UNIX文件系统布局或许会有利于一个由通用开元组件构建的多用户系统(查阅http://www.pathname.com)。另一方面,一个安全的嵌入式系统可能更适合采用一种避免联合路径(即任何由多个资源管理器提供服务的路径)的布局,并且其中的某些文件被限制为只读、已验证且可能加密的文件系统。

QNX Neutrino 系统中的文件布局主要由以下因素决定:

  • 每个资源管理器的挂载点(一般被查工作"附载点")
  • 每个文件在资源管理器中的相对路径

文件系统资源管理器,包括提供主映像文件系统 IFS的资源管理器,都可以挂载到路径空间中的任意位置。IFS 默认挂载在 /,并为 IFS 中的所有对象添加 proc/boot 前缀。这造成了以/proc/boot开头的任何文件永远都会先查询到procfs(/proc 资源管理器),这会轻微影响性能。你可以通过mkifs 构造文件中送[prefix=""] 和 [mount="/ifs"]选项来挂在IFS到/ifs 来避免这个问题。

当你正在填充一个可以被挂在在任何位置的文件系统时,应避免绝对路径和系统挂载位置的假设。例如防断电文件系统中的路径lib/libfoo.so,当系统被挂在路径空间的根目录时会变成/lib/libfoo.so,而被挂载在/fs/qnx6时会变成/fs/qnx6/lib/libfoo.so。系统中请求这一路径的路径管理器会被路由到正确的资源管理器。

很多针对设备的资源管理器(和文件系统资源管理器不同),会把他们的挂载点硬编码,典型的会在/dev下。但这一般并不是强制要求,如果你发现你的设备管理器和你系统的布局有冲突,你或许会希望和资源管理器的提供商联系并让他们更改。(或者更好的,允许你使用命令行指定挂载点)。

然而,也有很少一部分路径是必须要存在在QNX Neutrino 系统中。
/usr/lib/ldqnx.so.2 or /usr/lib/ldqnx-64.so.2

实时连接器(也叫动态连接器)。在所有QNX Neutrino 操作系统中这个路径都是硬编码的

/.boot (仅x86_64)

存放基于BIOS的系统所需要的所有IFS二进制文件的目录。

本章节的其余部分将描述QNX Neutrino 版本的传统UNIX布局。

/bin

bin 目录包含了基础指令的二进制文件,例如 chmod、ls以及ksh

在命令行中输入 "use 指令名"来显示基础指令的语法。更多信息请参考《指令指南》

/dev

/dev 目录诗雨资源管理器,它包含了设备文件,可能包含了:
/dev/cdn

CD-ROM块设备。参考《指令指南》中的devb-*来获取更多设备信息。
/dev/conn

TTY控制台设备的文字模式。参考《指令指南》中的devc-con。
/dev/console

用于诊断日志信息的设备。在一个完整的x86系统中,这是个由系统记录器管理的只写设备,slogger2。嵌入式系统的构造文件可以在其他设备中配置一个该路径的链接,例如一个串口。参考《指令指南》中的slogger2。
/dev/hdn

硬盘块设备。数据代表了整个驱动,跨越所有分区。参考《指令指南》中的devb-*。
/dev/hdntn

硬盘块设备。这些设备中的数据是hdn对应数据的子集。参考《指令指南》中的devb-*。
/dev/mem

一个代表了所有物理内存的设备。
/dev/mq和/dev/mqueue

消息队列条目所在的路径空间。更多信息请参考《指令指南》中的mq和mqueue。
/dev/null

一个你可以将数据导入其中的'位桶'(bit bucket)。这些数据被丢弃了。
/dev/pci

当前机器上适配PCI服务器的设备,该设备允许程序和PCI服务器通讯。参考《指令指南》中的pci-*
/dev/pipe

适配管道管理器。这个文件的存在告诉其他程序(例如构建在OS镜像中启动脚本)管道管理器已成功运行。
/dev/pty[p-zP-T][0-9a-f]

伪终端设备对中的控制端。伪ttys用字母(p-z或P-T)加十六进制数字命名,使其最多又256个设备。请参考《指令指南》中的devc-pty。
/dev/random

从这个设备读取随机数据。请参考《指令指南》中的random。
/dev/sem

信号量所在的路径空间。
/dev/sern

串口。相关配置请查看stty,更多设备信息请参考《指令指南》中的devc-ser*
/dev/shmem/

包含了系统中代表共享内存区域的文件(有时也被通用内存映射文件使用)。更多信息请参考文件系统操作中RAM文件系统的相关描述。
/dev/socket/

这个目录是TCP/IP栈所有并管理的,它包括了io-ptk*。这个目录包含了应用和栈交互的路径名。更多信息请参考TCP/IP网络章节。
/dev/text

这个文件被procnto管理。写入这个设备的文字是通过调式输出路径编码在你系统的开机代码中的输出,因此每个板子是不同的。在标准的电脑上,默认事故写入电脑的控制台。更多信息请参考《指令指南》中的startup-*
/dev/tty

由进程管理器(procnto)拥有的虚拟设备。任何进程打开此文件时,它都会解析为该进程所在会话对应的控制终端设备。这对于程序来讲是非常有用的,它们或许已经关闭了它们的标准输入、标准输出、标准报错并希望把这些写入终端设备。
/dev/tty[p-zP-T][0-9a-f]

/dev/pty[p-zP-T][0-9a-f]对应的从端文件。典型地,程序一般被这些文件中的一个控制其准输入、标准输出、标准报错。
/dev/zero

提供一个无限长的字节流,其中每个字节的值均为零。

/etc

/etc 目录包含了主机专属的系统文件和程序,用于管理权限、配置,包括:
/etc/config/

包含了系统配置文件的目录,例如ttys 文件,它被tinit用于配置终端设备。
/etc/default/

包含默认配置文件的目录,主要用于TCP/IP设置
/etc/dhcpd.conf

动态主机配置协议。请参考《指令指南》中的/etc/dhcpd.conf
/etc/ftpd.conf

文件传输协议(ftpd)的配置选项,一旦你连接或者授权时就会被应用。请参考《指令指南》中的.../.../com.qnx.doc.neutrino.utilities/topic/f/ftpd.conf.html
/etc/ftpusers

定义了哪些用户可以通过文件传输协议访问机器。请参考《指令指南》中的/etc/ftpusers
/etc/group

用户账户分组定义。参考《管理用户账户》章节
/etc/hosts

网络主机名查找数据库,参见下述/etc/nsswitch.conf 和 /etc/resolv.conf。请参考《指令指南》中的/etc/hosts
/etc/inetd.conf

互联网超级服务器配置文件,定义了inetd动态开启和关闭时所需的互联网服务。

  • 该文件中默认版本的描述被注释掉了,没有被注释掉的是你需要。请参考《指令指南》中的/etc/inetd.conf

/etc/motd

包含了一条用户登录时会显示的ASCII信息,是否显示取决于/etc/profile中配置是否会显示它。

只有当/etc/motd 文件比你最后一次登录系统时间(取决于 $HOME /.lastlogin的修改时间)更晚时, /etc/profile默认会显示此文件。更多信息,请参考配置你的系统章节中关于/etc/profile的描述
/etc/networks

网络名数据库。更多信息参考《指令指南》中的/etc/networks
/etc/nsswitch.conf

命名服务控制配置文件。更多信息《指令指南》中的/etc/nsswitch.conf
/etc/opasswd

/etc/passwd 最后一次通过passwd指令修改/etc/passwd前的备份。请参考管理用户账户章节。
/etc/oshadow

/etc/shadow 最后一次通过passwd指令修改/etc/passwd前的备份。请参考管理用户账户章节。
/etc/passwd

该文件定义了登录账户,更多信息请参考登录、登出和关机章节和管理用户账户章节。也可以参考《指令指南》中的passwd , login
/etc/profile

启动用户配置脚本,当你登录时命令行解释器会执行它。它会在$HOME /.profile前被执行。参看配置你的环境章节。
/etc/profile.d/

默认/etc/profile脚本会在此目录下寻找任一用户登录的脚本。/etc/profile脚本会运行此目录下每个和*.$(SHELL##/}匹配的脚本。例如如果命令行解释器中环境变量的值为/bin/sh,那么该脚本会运行所有匹配 .sh的脚本。
/etc/resolv.conf

解析器配置文件,参见上述/etc/hosts。请参考《指令指南》中的/etc/resolv.conf
/etc/skel/

存放.profile默认版本的目录。当你在系统中增加新用户时,这个文件会被复制到用户的home目录。更多信息请参考/etc/default/passwd的描述以及配置你的系统章节的.profile

/home

常规用户的home目录存放在这里。你的目录名和你的用户名是一致的。你可以在你的home目录下创建你需要的任何目录结构

lib

这个目录包含了基础的共享库和运行所需的程序(文件名 .so),以及开发中所需的静态库。请参考/usr/lib 和 /usr/local/lib.

/lib目录包括:
/lib/dll/

包含了实现OS驱动和服务的补充共享库,例如驱动、文件系统管理器等。更多关于具体类型的驱动和服务如何使用共享库,请查看《系统架构指南》中的文件系统、原生网络(Qnet)和TCP/IP网络。关于/lib/dll中的特定共享库的详细信息,请参考《指令指南》中它们各自的条目。

/proc

属于进程管理器(procnto),这个虚拟目录可以向你提供关于进程和路径名空间配置的信息。

每个进程都在 /proc 目录下有一个子目录,以进程 ID命名。每一个子目录都包含了用以访问进程地址空间的条目(如果有适当的权限)来控制它们的线程等。许多指令会用到这些条目来获取进程的信息。更多信息,请参考《QNX Neutrino程序员指南》中的"通过/proc 文件系统控制进程"章节以及《QNX Neutrino Cookbook》中/proc文件系统附录。
/proc 目录下也包含以下内容:
/proc/boot/

包含了启动引导镜像的文件系统镜像。更多信息请参考《构建嵌入式系统》中的操作系统镜像章节
/proc/dumper

一个接收进程异常结束提醒的特殊条目。dumper指令创建了此条目。
/proc/mount/

路径名空间的挂载点。

  • 如果里列出/proc下的内容,/proc/mount并不会在其中,但你可以列出/proc/mount中的内容

更多信息请参考《QNX Neutrino Cookbook》中/proc文件系统附录中的/proc/mount目录

/proc/qnetstat

如果你在使用透明分布式处理(TDP),lsm-qnet.so 模块会在/proc中放一个qnetstats 条目。如果你打开这个名字并从中读取,Qnet资源管理器的代码会对当前Qnxt的统计进行反馈。
/proc/self

你自身的地址空间(为正在进行查询的进程)

/root

/root 目录是root用户的home目录

/sbin

包含系统基础的二进制文件,包括:

  • 驱动(devb* , devc* , devf* , devu*)
  • 初始化程序
  • 配置命令(ifconfig)和修复指令(chkqnx6fs , chkdosfs)
  • 管理器(io-pky*,mqueue,pipe)
/tmp

这个目录包含临时文件。一般假设程序会在使用完后删除它们的临时文件,但有时由于不好的代码质量和异常中断它们并不这样做。你可以在系统空闲时定期清理无用的文件。

/usr

/usr 目录是一个次级文件层次结构,包含可共享的只读数据。它可能会包含以下内容:
/usr/bin/

一个包含了用户最常用指令的目录。例如diff,errno和wc
/usr/lib/

对象文件,库和你不能直接执行或使用脚本执行的中间二进制文件,你会在写程序时链接这些库。
/usr/libexec/

可能包含了守护进程和系统指令,总的来说它们只会被其他程序运行
/usr/local/

最开始是空的,系统管理员可以在此安装软件到本地。
/usr/sbin/

非基础系统二进制文件例如cron、dumper和nocinfo
/usr/share/

和架构无关的数据,例如图标、壁纸和各种gawk程序

/var

/var 路径包含各种数据文件,包括缓存文件、锁文件、日志文件等。
/var/pps

持久化发布/订阅管理器 pps 在关闭时存储("持久化")其状态的目录。

用户所有权和权限

每个文件和目录都鼠疫一个特定的用户ID和组ID,并有一系列相关的权限(也叫模式)。

你可以使用这些指令来控制所有权和权限:

目的 指令

指定文件或目录的权限 chmod

改变文件或目录的所有者(或组别) chown

改变文件或目录的组别 chgrp

更多细节请参考《指令指南》

*只有当你是文件或目录的所有者或者你以root身份登录时你才可以改变文件或目录的权限,如果你既要修改权限又要修改所属权,请先修改权限。一旦你把所属权分配给了其他用户,你就无法修改全线路。

权限类别的划分:
u

用户权限(指所有者)
g

组的权限
o

其他用户的权限(指组以外的所有人)

每个权限包括:
r

读的权限。对于目录来说,这是允许列出目录下内容的权限。
w

写的权限
x

执行的权限。对于目录来说,这是允许在目录下查找的权限。
s或S

Setuid 或 setgid (见下述描述)。
t或T

粘滞位(见下描述)

如果你对目录有读的权限但没有搜索的权限,你可以看到目录下的文件,但是无法读取或修改这些文件的内容。如果你对某个目录(假设它是dir)有搜索的权限但是没有读的权限的,但是对他的子目录(假设是dir/subdir)有读的权限,那么你无法再dir路径下列出所有内容并看到subdir,但是如果你(出于某种原因)知道dir/subdir的存在,你可以直接指定并列出dir/subdir中的内容。

如果你列出你home目录下的内容(使用ls -al),你或许会得到以下输出:

bash 复制代码
total 94286
drwxr-xr-x 18 barney techies   6144 Sep 26 06:37 ./
drwxrwxr-x  3 root   root      2048 Jul 15 07:09 ../
-rw-rw-r--  1 barney techies    320 Nov 11  2013 .kshrc
-rw-rw-r--  1 barney techies      0 Aug 08 09:17 .lastlogin
-rw-r--r--  1 barney techies    254 Nov 11  2013 .profile
-rw-rw-r--  1 barney techies   3585 Jul 31  1993 123.html
-rw-rw-r--  1 barney techies    185 Aug 08  2014 Some_file
drwx------  2 barney techies   4096 Jul 04 11:17 bin/
-rw-------  1 barney techies     34 Jul 05  2002 cmd.txt
drwxr-xr-x  2 barney techies   2048 Feb 26  2014 interesting_stuff/
drwxrwxr-x  3 barney techies   2048 Oct 17  2002 more_stuff/
drwxrwxr-x  2 barney techies   4096 Jul 04 09:06 workspace/

第一类是权限的集合。以d开头的表示这一项是目录。查看本章前面提及的"文件类型"

*如果某项权限后有一个加号(+),该文件或目录拥有一个访问控制列表,用于进一步明确权限。更多信息,请查看下述"访问控制列表(ACLs)"

你也可以查看表示权限的八进制数,查看《指令指南》中的chmod

Setuid 和 setgid

一些程序,例如passwd,需要特殊用户运行才能正常工作

bash 复制代码
$ which -l passwd
-rwsrwxr-x 1 root root 21544 Mar 30 23:34 /usr/bin/passwd

请注意所属权中的第三个字母是s。这代表了setuid("设置用户ID")指令。当你运行passwd时,程序会以文件的所有者的身份运行(这里是root)。S 表示文件的设置用户 ID(setuid)位已设置,但执行位未设置。

你也会找到一些setgid("设置用户组ID")指令,它们会使用文件所属的组id运行,但不是以所属的用户id运行。如果setgid被设置到了一个目录,那么这个目录下创建的文件会有这个目录的组id,而不是文件创建者的ID。这种方案通常用于假脱机区(spool areas),例如/usr/spool/mail,它是setgid 并且被mail组所有,因此以mail组身份运行程序可以更新这里的东西,但是文件仍属于它们自己的所有者。

  • 除非你以root身份登录,当你修改一个setuid 命令的归属权时,setuid 位会被清空。类似的,当你修改一个setuid 命令的归属权时,setgid 位会被清空。

当你在Windows主机上运行时,mkefs 、 mketfs和 mkifs无法从文件中获得执行(x)、setuid或setgid权限,使用perms属性来明确指定指定这些权限。你也可以使用uid和gid属性来正确的指定所属权。更多关于指令是否需要setuid 或 setgid权限,请查看《指令指南》中相关条目。

注意!
Setuid 和 setgid指令会造成安全问题。如果你创建了它们,需确认只有只有它们的所有者可以写入它们,其他可以用户不会黑掉他们,特别是那些被root拥有的文件。

粘滞位

粘滞位(sticky bit)是一种访问权限,它会影响对可执行文件和目录的处理方式

如果一个可执行文件设置了这个权限,内核希望程序结束后这个内存中的可执行文件还能保留"一段时间",具体时间长度取决于系统中会发生什么。当你经常运行一个程序时,这会提高性能。

如果这是一个目录,粘滞位会影响谁可以删除这个文件。要删除文件,你总需要对这个目录有写的权限,但是如果这个路径被设置了粘滞位,你也需要是这个目录的所有者或者对文件有写的权限。

如果权限中的第三个字母是t(例如r-t),那么粘滞位和可执行权限都被设置的了。T则代表只设置了粘滞位。

默认文件权限

使用 umask 命令来指定用于设置新文件权限的掩码。

默认掩码是002,因此所有的新文件会赋予用户(文件的所有者)和其他用户组读和写的权利,以及所有其他用户读的权利。如果你想移除其他用户读和写的权限,在.profile目录中增加如下指令:

umask 006

如果你是系统的管理员并且你希望对所有人应用这项更改,修改/etc/profile中的umask设置。更多信息请参考配置你的系统章节。

访问控制列表(ACLs)

一些文件系统例如防断电文件系统( fs-qnx6.so )使用访问控制列表来扩展文件权限。

传统的用户权限是使用chmod来设置文件全限定,如果你想要某些用户对一个文件有特别的权限,你只有很有限的一些选择:

  • 把那个人添加到所属组
  • 创建一个包含那个人和文件所有者的补充组别
  • 降低"其他"用户的权限

跟踪每个用户组的权限可能会变得复杂,允许"其他"用户更多的权限会让你的系统不那么安全。ACLs扩展了文件的权限,让你可以更好的管理谁可以访问什么。在ACLs中,权限被分为以下类别:

  • 所有者类
  • 组类别,由指定用户、属组和指定组组成。
  • 其他(或全局)类

访问控制列表包含了一系列条目,列举在如下表格中(通过代码中用于标识标签类型的常量来给出)

条目类型 标签类型 格式
所有者 ACL_USER_OBJ user::permissions
指定用户(用用户名或数字ID指定) ACL_USER user:user_identifier:permissions
所属组 ACL_GROUP_OBJ group::permissions
指定组(用组名或数字ID指定) ACL_GROUP group:group_identifier:permissions
组别权限上限 ACL_MASK mask::permissions
其他 ACL_OTHER other::permissions

权限遵从rwx格式,用横杆(-)替代没有授予的权限。

这是一个ACL文件的例子

bash 复制代码
user::rw-
user:violetta:r--
group::rw-
mask::rw-
other::---

所有者和所属组有读和写的权限。其他用户没有任何权限。violetta被授予了读的权限,她比"其他"有更多特权,但是不想所有者和所属组那么多特权。如果"violetta"没有被授予特俗权限,那么ACL和rw-rw----权限是一样的。

如果一个ACL可以简单到和文件权限一样,它可以被称作最小ACL。如果不能,它被称作扩展ACL。一个扩展ACL一定有一个掩码条目,也可以包含针对指定用户和制定组别任意多的掩码条目。如果一个文件有一个宽展ACL,那ls -l中输出的权限后会有一个加号(+)

掩码条目是一个所属组、所有指定用户、所有指定组别的权限几何。例如让我们来看一个文件,它的所属组没有写的权限

bash 复制代码
# ls -l file.txt
-rw-r--r-- 1 mabel techies 50 Sep 27 21:22 file.txt

如果我们用getfacl指令来获取它的ACL,我们可以看到:

bash 复制代码
# getfacl -q file.txt
user::rw-
group::r--
other::r--

-q 选项会抑制 getfacl 默认显示的某些注释,仅列出文件名、所有者和属组。下一步,让我们假设"mable"用setfacl给"frank"增加了一条授予他读和写权限的条目(要修改ACL,你必须是这个文件或目录的所有者,或者你有适当的特权)

bash 复制代码
# setfacl -m u:frank:rw- file.txt
# getfacl -q file.txt
user::rw-
user:frank:rw-
group::r--
mask::rw-
other::r--
# ls -l file.txt
-rw-rw-r--+ 1 mabel techies 50 Sep 27 21:22 file.txt

除了给"frank"的条目,ACL现在包括了一个列出了读和写权限的条目。ls的输出也表明组有读和写的权限。

修改文件权限(例如使用chmod)会影响ACLs,反之亦然。

  • 文件的用户权限和ACL中所有者的权限条目永远匹配
  • "其他"权限和ACL中"其他"权限的条目永远匹配
  • 如果ALC中没有掩码条目,那么组权限和ACL中的组权限条目匹配
  • 如果ACL中有掩码条目,那么组权限不一定和ACL中的组权限条目匹配

让我们继续来看这个文件的例子,现在"mable"使用库chmod移除了组的写入权限:

bash 复制代码
# chmod g-w file.txt
# getfacl -q file.txt
user::rw-
user:frank:rw-   # effective: r--
group::r--
mask::r--
other::r--
# ls -l file.txt
-rw-r--r--+ 1 mabetechies 50 Sep 27 21:22 file.txt

"frank"条目仍列出了读和写的权限,但是一条备注警告我们只有读的权限是有效的,因为我们在掩码中明确移除了写的权限。

以下伪代码展示了检查文件或目录访问权的算法

c 复制代码
if (the process's effective user ID matches the object owner's user ID)
{
    The matched entry is the owner ACL entry
}
else if (the process's effective user ID matches the user ID specified in any named user ACL entry)
{
    The matched entry is the matching named user entry
}
else if (the process's effective group ID or any of its supplementary group IDs
         matches the group ID of the object or matches the group ID
         specified in any named group entry)
{
    if (the requested access modes are granted by at least one entry
        matched by the process's effective group ID or any of its supplementary group IDs)
    {
        The matched entry is one of the granting entries (it doesn't matter which)
    }
    else
    {
        Access is denied
    }
}
else if (the requested access modes are granted by the "other" ACL entry)
{
    The matched entry is the "other" entry
}

if (the requested access modes are granted by the matched entry)
{
    if (the matched entry is the owning user or "other" entry)
    {
        Access is granted
    }
    else if (the requested access modes are also granted by the mask entry,
             or no mask entry exists in the ACL)
    {
        Access is granted
    }
    else
    {
        Access is denied
    }
}
else
{
    Access is denied
}

更多信息请参考《指令指南》中的 getfacl 或 setfacl。

你的程序也可以使用一些函数来操作ACLs,更多相关信息请参考《QNX Neutrino程序员指南》以及《QNX Neutrino C库指南》中的acl_*()条目

*POSIX 草案还描述了默认 ACL,这些默认 ACL 规定了在目录内创建的新对象的初始 ACL。目前尚未实现默认 ACL。
cp指令不会拷贝原文件的ACL,但如果目标文件已经存在ACL,那么这个ACL会被保留。

文件扩展名

下表列出了一些QNX Neutrino系统场景文件扩展名

展名 描述 相关程序/工具
.1 Troff 格式文本,例如来自 Unix "man"(手册)页面的内容。 man 和 troff(第三方软件)
.a 库归档文件 ar
.awk Awk 脚本 gawk
.b 基准计算器库或程序 bc
.bat MS-DOS 批处理文件 用于 DOS 系统;在 QNX Neutrino 下无法运行。有关为 QNX Neutrino 编写 shell 脚本的信息,请参阅"编写 Shell 脚本"和 ksh。
.build 操作系统镜像构建文件 mkifs
.c C 程序源代码 qcc, make
.C, .cc, .cpp C++ 程序源代码 q++, make
.cfg 配置文件,各种格式 各种程序;格式不同
.conf 配置文件,各种格式 各种程序;格式不同
.css 层叠样式表 在 IDE 中用于文档
.def C++ 定义文件 q++, make
.dll MS-Windows 动态链接库 不直接在 QNX Neutrino 中使用;某些在 MS-Windows 下运行的程序(例如部分 QNX Neutrino 工具)需要。等效的 QNX Neutrino 格式请参阅 .so(共享对象)。
.gz 压缩文件 gzip;另请参阅"备份与恢复数据"
.h C 头文件 qcc, make
.htm 用于网页浏览的超文本标记语言(HTML)文件 网页浏览器
.ifs, .img QNX Neutrino 镜像文件系统,通常是可启动镜像 mkifs;另请参阅《构建嵌入式系统》中的"操作系统镜像"
.jar Java 归档文件,由多个 Java 文件(类文件等)压缩成单个文件 Java 应用程序,例如 IDE
.kev 内核事件,由插桩内核收集,用于分析整个 QNX Neutrino 系统 procnto*-instr, tracelogger, traceprinter, IDE;另请参阅《系统分析工具包用户指南》
.mk Makefile 源文件,通常在 QNX Neutrino 递归 make 中使用 make
.o 编译 C、C++ 或汇编源文件后产生的二进制输出文件 qcc, make
.S, .s 汇编源代码文件 GNU 汇编器 as
.so, .so.n 共享对象 qcc, make
.tar 磁带归档 tar;另请参阅"备份与恢复数据"
.tar.gz, .tgz 压缩的磁带归档 gzip, tar;另请参阅"备份与恢复数据"
.txt ASCII 文本文件 许多基于文本的编辑器、应用程序和用户
.use 用于未将用法信息嵌入程序源代码的程序的用法消息源(QNX Neutrino 递归 make) make
.wav 音频波形文件
.xml 可扩展标记语言文件;多种用途,包括 IDE 文档
.zip 压缩归档文件 gzip

如果你不确定你文件的类型,使用file指令

bash 复制代码
file 文件名
故障排查

以下是你可能遇到的一些问题:
我试图写入一个文件,但收到了"权限被拒绝"的提示。

你没有写入该文件的权限,如果你是文件的的所有者(或root),你可以修改权限。查看上述"文件所属权和权限"。

我有目录写入权限,当我试图列出目录内容,却收到了"权限被拒绝"的提示。

你需要读取权限才能列出目录内容,以及执行权限来对目录下的内容操作。查看上述"文件所属权和权限"。

文件名中有空格时会出问题

命令解释器或shell会使用空格字符来将命令拆分成命令词。如果你的文件名中包含空格,你需要用"引号"把空格引用起来,让shell知道这就是一个真实的空格。更多信息,包括其他你需要了解的特殊字符,请参考使用命令行章节的引用特殊字符。

相关推荐
ambition202421 天前
UNIX消息队列:从理论模型到工程实现的演进
linux·服务器·unix
WangLanguager3 天前
Unix 命令 rm详细介绍
linux·服务器·unix
kyle~8 天前
调试器---GDB(Linux/Unix平台下编译型语言,C++、Go、Rust)
linux·c++·unix
WangLanguager12 天前
Unix架构详细介绍
arm开发·架构·unix
LIUAWEIO13 天前
Unix 时间戳换算
前端·后端·unix·database
風清掦17 天前
【STM32学习笔记-12】Unix 时间戳、BKP 备份寄存器与 RTC 实时时钟
笔记·stm32·单片机·嵌入式硬件·学习·实时音视频·unix
郝学胜-神的一滴19 天前
跨平台动态库与头文件:从原理到命名的深度解析
linux·c++·程序人生·unix·cmake
郝学胜-神的一滴23 天前
epoll 反应堆模型深度拆解:从红黑树到回调闭环,手写高性能回射服务器
linux·运维·服务器·开发语言·c++·unix
♛识尔如昼♛23 天前
C 进阶(1) - Unix 基础
unix