一、内存的映射
将一块物理地址映射到进程的虚拟地址空间
将一个文件映射到进程的虚拟地址空间,在虚拟地址空间进行数据改变,这些改变将同步到底层文件
mmap(2)
#include<sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flogs, int fd, off_t offset)
功能:将文件或设备映射到内存
参数:
addr:指定了映射区域的起始位置,输入NULL代表内核自动选择
length:指定映射区域的长度
prot:选择一个或者多个
①PROT_EXEC:执行
②PROT_READ:读
③PROT_WRITE:写
④PROT_NONE:无权限
flags:二选一
①MAP_SHARED(共享)
②MAP_PRIVATE(私有)
注:
物理地址空间中,有些设备没有文件名,这些设备的确是一个文件但没有记录到文件管理系统中,这类文件称为匿名文件
共享映射:对映射区域的更新可以被另外一个映射同一文件的进程看到,并且同步到底层文件中
私有映射:对映射区域的更新不能被另一个映射同一文件的进程看到,并且不同步到底层的文件中
MAP_ANOYMOUS可以或到flag标记中,表示匿名映射,此时fd被设置成-1,offset被忽略
fd:指定了文件的描述符,将此文件映射到进程的虚拟地址空间
offet:指定了文件映射的起始位置,必须是页的整数倍
返回值:
成功:返回映射区域的起始位置
失败:MAP_FAILED被返回,errno被设置
int munmap(void*addr,size_t length);
功能:解除文件或设备到内存的映射
参数:
addr:指定映射区域的起始位置
length:指定长度
返回值:
成功:返回0
失败:返回-1,errno被设置
私有映射:
共享映射:
二、文件的元数据
文件有两部分组成:文件内容和描述信息
ls -l显示的文件属性中除文件名外都是文件的元数据
ls -li显示的最前面的数字是inode号
每个文件有且仅有一个对应的inode号
两个文件如果共用一个inode号就是硬链接
软连接:
data中包含十五个元素的整型数组(数据块),每个块有一个编号4个字节,放数据块的地址
数据块地址指向存储空间,一般指向一页大小的存储空间,也可以开辟更多的空间,让指向的4k地址存编号,在分别指向存储空间,4k内存可以存储1k个编号,这样就可以存储1k*4k的大小空间,如果不够还可以继续这样分配
用stat(2)来获取文件的元数据,不适用于软连接
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
int stat(const char *pathname,struct stat*buf);
功能:获得指定文件的元数据
参数:
pathname:指定了要操作的文件路径
buf:将文件的元数据存储到buf指定的地址空间中
返回值:
成功返回0
错误返回-1
struct stat{
dev_t st_dev;//设备ID
ino_t st_ino;//文件对应的inode号
mode_t st_mode;//权限
nlink_t st_nlink;//硬链接数
uid_t st_uid;//属主ID,输出的是一串数字
gid_t st_gid;//属组ID,输出的是一串数字
dev_t st_rdev;//设备ID
off_t st_size;//文件尺寸
blksize_t st_blksize;//文件系统IO
blkcnt_t st_block;
struct timespec st_atim;//最后访问时间,所得到的时间都是秒
struct timespec st_mtim;//最后修改时间
struct timespec st_ctim;//最后状态修改时间
#define st_atime st_atim.tv_sec
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
struct timespec{
_time_t tv_sec;
_syscall_slong_t tv_nsec;
};
如何看结构体中定义的类型用什么占位符呢
gcc -E生成.i文件即可在.i文件中查看
用户信息存放在/etc/passwd中 ,当我们查看会发现它是冒号分割的七列数据
分别是:
用户名:用户是否有密码:用户ID:组ID:对用户的说明信息:用户家目录:用户登陆成功后执行的第一个程序
但当我们用ls -l查看文件时显示的是用户名和用户组名
如何将uid和gid的数字转换成我们常见的用户名和用户组名的字符串形式呢
getpwuid(3)和getgrgid(3)这两个库函数可以完成
#include<sys/types.h>
#include<pwd.h>
struct passwd*getpwuid(uid_t uid)
功能:获得与uid匹配的用户数据
参数:
uid:指定uid,从文件中找与uid匹配的记录
返回值:
失败:NULL,无匹配记录,errno被设置
成功:返回地址
struct passwd{
char *pw_name;//用户名
char*pw_passwd;//用户名password
char*pw_gecos;//用户信息
uid_t pw_uid;//用户ID
gid_t pw_gid;//用户组ID
char*pw_dir;//用户家目录
char*pw_shell;//shell program
}
struct group*getgrgid(gid_t gid);
功能:查找与gid匹配的记录
参数:
gid:指定要找的gid
返回值:
失败返回NULL,无匹配或错误,errno被设置
成功返回一个地址
struct group{
char*gr_name;//组名字
char*gr_passwd;//组密码
gid_t gr_gid;//组ID
char**gr_men;//组成员
}
如何转换我们所得到的时间呢,我们得到的时间是从1970年1月1日0:00开始计时的秒数
可以使用ctime这个函数来进行转换
文件权限上和类型我们想得到我们平时看的那种方式,类型用-,b,c,d等表示,权限用r、w、x、-表示该如何转换呢
类型:
S_IFMT是类型掩码,用我们得到的st_mode&S_IFMT所得到的数下面的进行对比,是哪个对应的即是哪种类型,此外系统还定义了一组宏,也可以来查看是什么类型的文件
权限:
和文件类型相同,使用s_mode分别与这些宏相与,不为0代表有此权限,为0代表无此权限
下面用代码使用以下看看:
三、文件夹操作
ls -la是显示所有文件的命令,创建和删除对于文件夹来说相当于写操作,文件夹是不能执行的,所以这里的执行代表着可通过的意思,例如使用cd
如何在程序中访问文件夹的内容
opendir(3) 、closedir(3)、readdir(3)
#include<sys/types.h>
#include<dirent.h>
DIR*opendir(const char *name);
功能:打开一个文件夹
参数:文件夹名字
返回值
成功返回一个指向文件夹流的指针
失败返回NULL,errno被设置
int closedir(DIR*dirp);
功能:关闭文件夹流
参数:
dirp:要关闭的文件夹流
返回值:
成功返回0
失败返回-1,errno被设置
#include<dirent.h>
struct dirent*readdir(DIR*dirp);
功能:从文件夹流中读取一条信息
参数:指定了文件夹流
返回值:
成功返回一个指向struct dirent结构体的地址
失败返回NULL,errno被设置或者是到达文件夹末尾
写个代码看一下
还有一些其他的函数,不具体展开了,需要用时可以用man手册查一下
access(2)查看权限、basename(2)获取路径文件夹、dirname(3)解析路径、chdir(2)改变工作路径、getcwd(3)获取当前工作路径、mkdir(2)创建文件夹
chmod(2)改变文件权限、link(2)硬链接、unlink(2)解除硬链接、symlink(2)软链接、rename(2)改变名字或位置、remove(3)移除文件夹......