4.10 粘着位
在早期的操作系统中,未使用分页技术。程序在磁盘上是随机存储的,则在装入程序是会耗费较大的时间,为保证下次执行程序时能将程序正文快装入内存,操作系统在磁盘上开辟了块交换区。交换区的文件是连续存储的,装入速度相对会更快。
现在操作系统使用分页技术,因此不再使用这种技术。但一般都扩展了这个位:
在文件的mod中S_ISVTX 位,表示粘着位,现代OS常用来限制一般用户对目录下文件的删除和重命名文件操作,但提供读写操作!
现代OS中如果设置了目录I_SVTX位,则只有拥有写权限,且拥有下列之一的权限才能删除和重命名目录下文件:
1.拥有文件
2.拥有目录
3.超级用户
4.11 修改文件所有者
chown(const char* pathname, uid_t owner, gid_t group);
fchown(int fd, uid_t owner, gid_t group);
fchownat(int fd, const char* pathneme, uid_t owner, gid_t group, int flag);
lchown(const char* pathname, uid_t owner, gid_t group);
四个函数修改文件的用户ID,组ID;
- 当owner 或group 有一个是-1时,id不变(owner,group 都不变)
- _POSIX_CHOWN_RESTRICTED:
- 有两种关于文件修改权限的情况:
- 只有超级用户才能修改owner
- 允许用户修改,对修改加以限制(设置了_POSIX_CHOWN_RESTRICTED ,只修改自己拥有的文件的组ID到,用户所属的组当前或者其他组)
4.17符号链接
1) 符号链接相对硬链接而言,硬连接是直接指向inode,而符号链接是在文件的数据中记录了文件的名字。
硬连接的限制:
1.只能指向同一文件系统(符号链接不是指向的inode所以可以指向任意系统) 2.指向目录的硬连接只能由内核执行(OS支持的前提下),为了防止循环链接(符号链接也能引起循环,一般查找路径的函数会错误返回,相比硬连接的文件系统错误,此错不会这么致命)
2)在处理文件时候要注意函数是否具有处理链接的能力
1.一般l开头的都直接处理链接不延伸到所指文件,lstat,lchown。。
2.f开头的函数以fd为处理参数,对于链接处理的控制优open完成(open打开是处理所指文件,openat可指定是否follow链接)。
3.mdir,rmdir,mkinfo,mknod则在处理链接时直接返回-1
3)符号链接可能导致指向不存在的文件,链接是不会检查!
csl@ubuntu:~$ ln -s /no/file nofile
csl@ubuntu:~$ ls
csl@ubuntu:~$ cat nofile
cat: nofile: No such file or directory
csl@ubuntu:~$
文件ls显示存在nofile ,却读不出来
4.18创建&读取符号链接
创建链接
int symlink(const char* actualpath, const char* symblpath);
int symlinkat(int fd, const char * actualpath, int symfd, const char*sympath);
打开链接本身,不读所指文件
int readlink(const char* sympath,char *rstrict buf, size_t size);
int readlinkat(int fd, const char* sympath, char* buf, suze_t size );
4.19文件时间
st_atime 系统的最近访问时间,注意之际录数据的访问时间,对属性修改不会记录
st_ctime 系统的最近修改时间,记录的是文件inode的修改时间也就算属性的修改时间,系统不记录inod的访问时间,也就是访问系统哦功能属性时时间不会记录
st_mtime 文件数据的最近修改时间
遍历文件目录
#include <iostream>
#include <unistd.h>
#include <sys/stat.h>//S_ISDIR
#include <stdlib.h>
#include <string.h>
#include <dirent.h>//dirent DIR
using namespace std;
int c = 2;
const int MAX = 256;
char *path;
int pathlen;
static void dopath();
static void myftw(const char *pathname)
{
//cout << pathname<<endl;
if((path = (char *)malloc(MAX)) != 0)
{
pathlen = 256;
}
else
{
cout << "分配内存失败!"<<endl;
return ;
}
if(pathlen < strlen(pathname))
{
pathlen *= 2;
if(( path = (char *)realloc(path, pathlen)) == 0)
{
cout << "内存 出毛病了!"<<endl;
return ;
}
}
strcpy(path, pathname);
dopath();
}
static void dopath()
{
struct stat statbuf;
if(lstat(path, &statbuf) < 0)
{
cout << "stat 出毛病了!"<<endl;
return ;
}
if(S_ISDIR(statbuf.st_mode) == 0)// 判断是不所目录
{
for(int i = 0; i < c; i++)cout << " ";
cout << path<<endl;
return;
}
int n = strlen(path);
if(n + NAME_MAX + 2 > pathlen)
{
pathlen = max(n + NAME_MAX + 2 , pathlen * 2 );
path = (char *)realloc(path, pathlen);
}
path[n++] = '/';
path[n] = 0;
for(int i = 0; i < c; i++)cout << " ";
cout << path<<":"<<endl;
DIR *dirp;
if((dirp = opendir(path)) == NULL)//
{
cout << "dir open faild!!!"<<endl;
return;
}
// sleep(1);
struct dirent *direp;
int i = 0;
while((direp = readdir(dirp)) != NULL)//逐条读取文件目录,直到文件末尾
{
if(strcmp(direp->d_name, ".") == 0 || strcmp(direp->d_name, "..") == 0 )continue;
strcpy(path + n, direp->d_name);
c+= 2;
dopath();
c-=2;
} path[n - 1] = 0;
closedir(dirp);
}
int main(int argc, const char *args[])
{
myftw(args[1]);
cout << "Hello world!" << endl;
return 0;
}
4.24特殊设备(待研究)
st_dev ,st_rdev 通常dev_t 高为表示主设备号,低若干位表示次设备号
每个文件系统所在的存储系统有主次设备号
主设备号标示驱动程序
次设备号标示特定子设备
只有字符设备& 块设备才有st_rdev 值
major minor两个宏可的主次设备号值
du & df
du -sh命令通过将指定文件系统中所有的目录、符号链接和文件使用的块数累加得到该文件系统使用的总块数;
而df命令通过查看文件系统磁盘块分配图得出总块数与剩余块数。
文件系统分配其中的一些磁盘块用来记录它自身的一些数据,如i节点,磁盘分布图,间接块,超级块等。这些数据对大多数用户级的程序来说是不可见的,通常称为Meta Data。
du命令是用户级的程序,它不考虑Meta Data,而df命令则查看文件系统的磁盘分配图并考虑Meta Data。
因此正常情况下,df计算的USED空间会比du计算的结果要稍大。