第四章笔记

4.2函数 stat类

//四个函数的返回值:若成功返回0,若出错返回-1;
int stat(const char * restrict pathname, struct stat * restrict buf);//返回与此命名的文件有关的信息结构
int fstat (int fd , struct stat * buf);//描述符fd上打开的有关信息
int lstat(const char * restrict pathname, struct stat * restrict buf);//返回该符号链接的有关信息
int fstattat(int fd, const char * restrict pathname, struct stat * restrict buf, int flag);//相对于当前打开目录的路劲名返回文件的统计信息。

lstat()函数和stat函数的区别:lstat()函数检测符号链接,使用stat函数观察不到符号链接。

4.3文件的类型:

unix下文件的类型包括:
1、普通文件
2、目录文件//每个进程可以读该目录文件的内容,但是只有内核可以直接写目录文件。
3、块特殊文件//每次访问以固定的长度为单位
4、字符特殊文件 //每次访问长度可变
5、FIFO(管道)//用于进程间的通信
6、套接字 //用于进程间的网络通信
7、符号链接]
unix系统中的所有设备文件要么是字符特殊文件,要么是块特殊文件。
文件类型的信息包含在stat结构的st_mode成员中,可以宏确定文件类型:
eg:S_ISREG(buf.st_mode)//确定文件是否是普通文件

4.4设置用户ID和设置组ID

设置ID的作用:主要表明文件归谁所有,文件访问权限的检查。
通常,有效用户ID等于实际用户ID,有效组ID等于实际组ID。
每一个文件都有一个所有者和组所有者,所有者由st_uid指定,组所有者由st_gid决定

4.6新文件和目录的所有权

使用open或者creat创建新文件时:
新文件的用户ID设置为进程的有效用户ID。
组ID允许实现选择下列之一作为新文件的组ID:
1.新文件的组ID可以是进程的有效组ID。
2、新文件的组ID可以是它所在目录的组ID。

4.7 函数acess和faccessat

当用open函数打开一个文件时,内核以进程的有效用户ID和有效组ID为基础执行其访问权限测试
函数//两者成功返回0 ,失败返回-1;

int acess(const char * pathname, int mode);
int faccessatn(int fd, const char * pathname, int mode ,int flag);

mode
mode 说明
R_OK 测试读权限
W-OK 测试写权限
X-OK 测试执行权限

facessat()与access()函数的区别:
在一下两种情况下是相同的,一种是:pathname参数为绝对路径,另一种是fd参数取值为AT_FDCWD而 pathname为相对路径,否则faccessat计算相对于打开目录的pathname。
flag参数可用于改变faccessat的行为,如果flag参数为AT_EACCESS,访问检查用的是调用进程的有效用户ID和有效组ID。

4.8函数umask

umask函数为进程设置文件模式创建屏蔽字,并返回之前的值

mode_t umask(mode_t cmask);。//参数cmask是由文件的9个访问权限(S_IRGRP)位中的若干个按位或构成的

如果我们要确保任何用户都能读文件,则应该将umask设置为0,否则,当进程运行时,有效的mask值可能会关闭该权限位
用户可以设置umask值来控制他们所创建文件的默认权限,该值表示成八进制数。例如:002表示阻止其他用户写入你的文件

八进制数的形成:
在终端输入:
  ls -l xxx.xxx (xxx.xxx是文件名)
  那么就会出现相类似的信息,主要都是这些:
  -rw-rw-r–
  一共有10位数
  其中: 最前面那个 - 代表的是类型
  中间那三个 rw- 代表的是所有者(user)  然后那三个 rw- 代表的是组群(group) 最后那三个 r– 代表的是其他人(other)
  然后我再解释一下后面那9位数:
  r 表示文件可以被读(read) w 表示文件可以被写(write) x 表示文件可以被执行(如果它是程序的话) - 表示相应的权限还没有被授予
r 表示文件可以被读(read) w 表示文件可以被写(write) x 表示文件可以被执行(如果它是程序的话)
其中:rwx也可以用数字来代替
  r ————4 w ———–2 x ————1 - ————0
002 表示前三个中间三个均为0 后面那个010//后面那三个表示其他人,2 表示写所以阻止其他人的写入;
更多相关信息:http://www.jb51.net/article/14444.htm

文件权限默认情况下是第一次代码创建时得权限,如果第二次执行相同的程序代码即创建的文件名一样但是umask设置的值不一样,此时也无法修改文件的屏蔽字,只能通过chmod给文件修改或者调用chmod、fchmod 、 fchmodat函数;

4.9函数chmod 、fchmod、 fchmodat

//三个函数返回值,若成功返回0,若失败返回-1

int  chmod(const char * pathname,  mode_t mode);   //在指定的文件上进行操作
int   fchmod(int fd,  mode_t  mode);   //已打开的文件进行操作
int fchmodat(int fd,  const char * pathname,  mode_t mode,  int flag);  //相对于打开目录的pathname,flag参数可以改变fchmodat的行为,既fd现在表示的是目录文件。

注意:mode可以设置为数字,但是要用八进制数表示既在数字前面加0(零)。
chmod 函数更新的只是i节点最近一次被修改的时间, ls -l 列出的是最后修改文件内容的时间。
改变一个文件的权限位,进程的有效用户ID必须等于文件的所有者ID,或者该进程必须具有超级用户权限。

4.10粘着位

粘着位:程序在第一次被执行,在其终止时,程序正文部分的一个副本仍被保存在交换区(程序正文部分的机器指令)
这使得下次执行该程序时能较快的将其载入内存。
现在的unix允许目录设置粘着位:
如果对一个目录设置粘着位,只有对该目录具有写权限的用户并且要满足下列条件之一,才能删除或重命名改目录下的文件:
1、拥有此文件
2、拥有此目录
3、是超级用户

4.12文件长度

stat 结构成员st_size 表示以字节为单位的文件长度,此字段只对普通文件、目录文件、和符号链接有意义
对于普通文件,其文件长度可以是0,在开始读这种文件时,将得到文件结束的指示。
对于目录文件,文件长度通常是一个数的整数倍(16或512的整数倍)。
对于符号链接,文件长度是在文件名中的实际字节数

4.13文件截断

文件截断的函数
有时需要在文件尾端处截去一些数据以缩短文件,一个特列是打开一个已存在的文件时,使用O_TRUNC可以做到这点、此外还可以调用一下两个函数。返回值,成功返回0 失败返回-1;

int truncate(const char * pathname,  off_t length);
int ftruncate(int fd, off_t  length);

//两个函数将一个现有文件长度截断为length,文件长度大于length则超过部分数据不在能访问,文件长度小于length,文件长度增加,形成文件空洞。

4.14文件系统

unix系统把一个磁盘分成一个或多个分区。每个分区可以包含一个文件系统,节点是固定长度的记录项。
—->>每个i节点都有一个链接计数,其值是指向该i节点的目录项数。只有将链接计数减少至0时,才可以删除该文件(即释放该文件所占据的数据块)//在stat结构中,链接计数包含在st_nlink成员中。
—–>>符号链接的实际内容(在数据块中)包含了该符号链接所指向的文件名字
—–>>当在不更换文件系统的情况下为一个文件重命名,该文件的实际内容并未为移动,只需构造一个指向现有i节点的新目录项,并删除老的目录项,链接计数不会改变。

任何一个叶目录(不包含其他目录的目录)的链接计数总是2 ,数值2来自于命名该目录的目录项,以及在该目录中的 .(点)项。

4.15创建和删除文件链接的函数:

创建一个指向现有文件链接的方法:
//两个函数的返回值,若成功返回0; 若出错返回-1;

int link (const char * existingpath , const char * newpath);//创建一个新目录项newpath,引用现有文件existingpath,如果newpath存在则出错。
int linkat( int efd,  const char * existingpath , int nfd,  const char * newpath, int flag)// 现有文件路径通过efd和existingpath来指定,新的路劲通过nfd和newpath来指定。flag参数设置了AT_SYMLINK_FOLLOW标志就是创建指向符号链接目标的链接(现有符号链接所指向的文件的链接)。如果该标志被清除了,则创建一个指向符号链接本身的链接

很多文件系统实现不允许实现对于目录的硬链接(因为这样做可能在文件系统中形成循环)。

软连接和硬链接的区别:
软连接相当于快捷方式,如果打开并修改软连接,相应的文件也会随之改变。但是如果删除软连接,源文件并不会受到影响。
硬链接有点像引用和指针的结合,当打开和修改它时,相应的文件随之改变,但是所有这个文件的硬链接的内容也随之改变,这是因为所有的硬链接都拥有唯一的一个 inode 号,他们指向的是同一文件。
软连接可以跨文件系统创建,也就是可以在某个分区中创建到另外一个分区的软连接
硬链接则只能在本文件系统中使用(想想为什么?),其实原理很简单,因为 inode 是这个文件在当前分区中的索引值,是相对于这个分区的,当然不能跨越文件系统了。
最后一个区别是软连接可以连接任何文件或者文件夹,而硬链接则只能在文件之间创建
来源: http://blog.chinaunix.net/uid-20797642-id-2974446.html

删除一个现有目录项:

int unlink(const char * pathname);
int unlinkat(int fd, const char * pathname,int flag);

flag参数:当AT_REMOVEDIR标志被设置时,unlinkat函数可以类似于rmdir一样删除目录,如果这个标志被清除,unlinkat与unlink执行同样的操作

remove函数也可以解除对一个文件或目录的链接。对于文件,remove的功能与unlink相同。对于目录remove的功能与rmdir相同。
int remove(const char * pathname);//成功返回0,出错返回-1
目录、目录项、索引节点
一个目录文件包含了一组目录项,目录项是放在data block中的。

一个目录项主要包括了文件名和索引节点号,索引节点号是指向索引节点表( system inode table )中对应的索引节点的。
或者这样解释一下目录项,因为目录可以包含子目录,目录是可以层层嵌套的,所以形成文件路径,而文件路径中的每一部分就是所谓的目录项(dentry)。
索引节点就是文件系统处理文件所需要的所有信息都存放在称为索引节点的数据结构中。主要就是文件的属性,包括链接数、文件所有者、文件建立和修改的时间,文件在磁盘的位置,文件大小、使用权限等等

来源: http://blog.chinaunix.net/uid-24807808-id-2569014.html

4.16文件的重命名

//成功返回0, 出错返回-1
int rename (const char * oldname, const char * newname);
int renameat(int oldfd,  const char * oldname,  int newfd,   const char * newname);

如果newname已经存在,则调用进程对它需要有写权限。另外,调用进程将删除oldname目录项,并可能要创建newname目录项,所以它需要对包含oldname以及newname的目录具有写和执行的权限。

4.17 符号链接

符号链接是对一个文件的简接指针,引入符号链接是为了避免硬链接的一些限制:
硬链接的限制:
1、硬链接通常要求链接和文件位于同一文件系统。
2、只有超级用户才能创建指向目录的硬链接。

对于符号链接以及他指向何种对象并无任何文件系统的限制,任何用户都可以创建指向目录的符号链接。符号链接一般用于将一个文件或整个目录结构移到系统中的另一个位置。

注意:使用符号链接可能在文件系统中引入循环。
用open打开文件时,如果传递给open函数的路径名指定了一个符号链接,那么open跟随此链接到达所指定的文件。若此符号链接所指向的文件不存在,则open返回出错,表示不能打开文件。

4.18创建或读取符号链接

//成功返回0,出错返回-1
创建一个指向actualpath的新目录项sympath
int symlink(const char * actualpath ,  const char * sympath);
int symlinkat(const char * actualpath, int fd, const char * sympath);

创建此符号链接时,并不要求 actualpath已经存在,且 actualpath和sympath并不需要位于同一个文件系统
打开符号链接:
//若成功返回读取的字节数,若出错返回-1
打开链接本身

ssize_t readlink(const char * restrict pathname, char restrict  buf, size_t bufsize);
ssize_readlinkat(int fd,  const char * restrict  pathname,  char * restrict buf , size_t bufsize);

4.19文件的时间

每个文件维护着三个时间字段 文件数据的最后访问时间(st_atim)、文件数据的最后修改时间(st_mtim)、i节点状态的最后更改时间(st_ctim)
i节点里存储的信息:文件类型、文件访问权限、文件长度、指向文件数据块的指针这些内容修改都会引起st_ctim的修改。
ls 命令按这3个时间值中的一个排序进行显示。-l 或-t 按照文件的修改时间的先后顺序排序。 -u按照访问的时间进行排序, -c
按照状态更改的时间进行排序。

4.20文件访问和修改时间的更改

//成功返回0, 出错返回-1

int futimens(int fd, const struct timespec time[2]);//需要打开文件来更改它的时间
int utimensat(int fd, const char * path, const struct timespec time[2], int flag);//利用文件名更改文件时间

times[2]数组参数的第一元素包含访问的时间,第二个元素包含修改时间

int utimes(const char * pathname , const struct timeval times[2])//对路径名进行操作。
struct timeval
{
time_t tv_sec;//秒
long tv_usec;//微妙
};

4.21对目录操作的函数

//创建一个新的空目录,成功返回0,出错返回-1;

int mkdir(const char * pathname, mode_t mode);
int mkdirat(int fd, const char * pathname, mode_t mode)//当fd参数为AT_FDCWD或者是绝对路径时两者一样

注意:目录的mode不能与文件的相同(即只设置读写),对于目录至少要设置一个执行权限位,以允许访问该目录中的文件名。
对目录具有访问权限的任一用户都可以读该目录,但是只有内核才能写目录,一个目录的写权限位和执行权限位决定了在该目录中能否创建新文件以及删除文件。

4.23 修改目录

//修改当前目录

int chdir (const char * pathname);//用pathname来新的当前工作目录。
int fchdir(int fd);//用打开的文件描述符来指定新的当前工作目录。
但是,每一个进程运行在独立的进程中,shell的当前工作目录并不会随着程序调用chdir而改变。因此,改变shell进程自己的工作目录,shell应当直接调用chdir函数。

查找当前工作目录(.)完整的绝对路径:
//成功返回buf, 出错返回NULL
char * getcwd(char *buf, size_t size);
//参数buf是缓冲区的地址,size是缓冲区的长度,缓冲区必须要有足够长的长度来容纳绝对路径名加上null

4.24设备特殊文件

1、每个文件系统所在的存储设备都有其主、次设备号表示。设备号所用的数据类型是基本系统数据类型dev_t。主设备号标实设备驱动程序;次设备号标实特定的子设备,一个磁盘驱动器上经常包含若干个文件系统,在同一磁盘驱动器上的个文件系统通常具有相同的主设备号,但次设备号确不同;
2、通常可以使用major和minor来访问主、次设备号。
3、系统中与每个文件名关联的st_dev值是文件系统的设备号,该文件系统包含了这一文件名与其对应的i节点。
4、只有字符特殊文件和块特殊文件才有st_rdev值。此值包含实际设备的设备号(磁盘设备是块特殊文件,终端设备是字符特殊文件)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值