在linux中,每一个硬件都对应一个文件(文件节点),就有了在linux中一切皆是文件的说法。
linux中的文件类型共有七种
1、“ - ”:普通文件
2、“ d ”:目录文件(directory)
3、“ l ”:链接文件(link)
4、“ p ”:管道文件(进程)(process)
5、“ s ”:套接字文件(网络)(socket)
6、“ b ”:块设备文件(block) ---> mount挂载
7、“ c ”:字符文件(char)
说到linux那就不得不说一下umask(文件默认创建权限掩码)
创建文件时有两种情况:
1.用户不指定各种文件访问者对于此文件都具有怎样的访问权限。
2.用户指定各种文件访问者对于此文件都具有怎样的访问权限。
在创建文件时,如果是情况1,那么文件最终的实际权限是通过文件默认创建权限和一个公式计算得出的。如果是情况2,那么文件最终的实际权限是通过用户指定的权限和公式计算得出的。
这个公式可以理解为数学上的函数,而这个函数要通过传递一个参数来进行结果的计算。如果是情况1,这个参数就是文件默认创建权限。如果是情况2,这个参数就是用户指定的权限。
因此,文件最终的实际权限其实并不一定和用户指定的权限相等。
umask可以影响文件和目录的起始权限(002)
文件起始权限(666) = (666)-umask(002)
目录起始权限(777) = (777)-umask(002)
可以使用chmod修改文件的权限,也可以修改umask显示文件实际的权限
目录io
那我们访问linux下的普通文件和访问目录有什么区别吗?
访问文件 ===》 得到文件里面的内容
访问目录 ===》 得到目录项的名字、属性、类型
目录函数接口如下
//1、打开目录
opendir()函数 ---> man 3 opendir
#include <sys/types.h>
#incldue <dirent.h>
DIR* opendir(const char* name);
参数说明:
name:需要打开的那个目录的路径
返回值:成功:目录流指针
失败:NULL
注意:opendir()打开一个目录并没有切换进去,利用chdir()切换目录
//2、切换目录
chdir()函数 ---> man 3 chdir
#include <unistd.h>
int chdir(const char* path);
参数说明:
path:需要切换的那个目录的路径
返回值:成功:0
失败:-1
//3、读取目录内容
readdir()函数 ---> man 3 readdir
#include <dirent.h>
struct dirent* readdir(DIR* dirp);
参数说明:
dirp:目录流指针
返回值:成功:结构体指针
失败:NULL ---> 当读取目录完毕,就会返回NULL
每读取一个目录项,就会返回一个结构体指针,来表达一个项的属性
struct dirent{
ino_t d_ino; //索引号
off_t d_off; //偏移量
unsigned short d_reclen; //记录文件名长度
unsigned char d_type; //文件类型
char d_name[256]; //文件名(重点掌握)
};
文件类型:
DT_BLK This is a block device. ---> 块设备文件 //6
DT_CHR This is a character device. ---> 字符设备文件 //2
DT_DIR This is a directory. ---> 目录文件 //4
DT_FIFO This is a named pipe (FIFO). ---> 管道文件 //1
DT_LNK This is a symbolic link. ---> 链接文件 //10
DT_REG This is a regular file. ---> 普通文件 //8
DT_SOCK This is a UNIX domain socket.---> 套接字文件 //12
//4、关闭文件
closedir()函数 ---> man 3 closedir
#include <sys/types.h>
#include <dirent.h>
int close(DIR* dirp);
参数说明:
dirp:目录流指针
返回值:成功:0
失败:-1
//5、重置文件指针
rewinddir()函数 ---> man 3 rewinddir
#include <sys/types.h>
#include <dirent.h>
void rewinddir(DIR* dirp);
参数说明:
dirp:目录流指针
返回值:无
文件函数接口如下
stat()函数 --> man 2 stat
作用:获取文件的属性
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
int stat(const char* pathname,struct stat* buf);
参数:pathname:路径名
buf:存储文件属性的结构体指针
返回值:成功:0
失败:-1
创建结构体对象:struct stat file_info
stat(path,&file_info);
存储文件属性的结构体信息
struct stat {
dev_t st_dev; //常规文件的ID
ino_t st_ino; //文件节点数字
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;//块大小,一个页大小
blkcnt_t st_blocks; //有几块数据,每一块数据是512字节
/* Since Linux 2.6, the kernel supports nanosecond
precision for the following timestamp fields.
For the details before Linux 2.6, see NOTES. */
struct timespec st_atim; //文件最近一次被存取或被执行的时间
struct timespec st_mtim; //文件最后一次被修改的时间
struct timespec st_ctim; //文件属性更改时间
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
用宏定义来判断文件的属性
S_ISREG(m) is it a regular file? //普通文件
S_ISDIR(m) directory? //目录文件
S_ISCHR(m) character device? //字符设备
S_ISBLK(m) block device? //块设备
S_ISFIFO(m) FIFO (named pipe)? //管道文件
S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.) //链接字套接字
S_ISSOCK(m) socket? (Not in POSIX.1-1996.) //套接字
使用方法:if((宏定义的一种)(struct stat name).st_mode)
测试代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
int main(int argc,char* argv[])
{
DIR* dp_name;
//char dir_path[] = "usr_data"; //目录路径
char *dir_path = "dir_name";
//打开一个目录
dp_name = opendir(dir_path);
if(dp_name == NULL)
{
perror("open dp fail");
return -1;
}
//需要切换路径进去
chdir(dir_path);
//循环读取目录项的内容
struct dirent* ep = NULL;
while(1)
{
ep = readdir(dp_name);//读完之后ep=NULL
//目录读取完毕之后退出
if(ep == NULL)
break;
//如果文件名的第一个字符是'.'不打印
//ep->d_name是字符数组类型,那么就可以取数组的第0个元素
if(ep->d_name[0] == '.')
continue;
printf("ep->name=%s\n",ep->d_name);
}
//关闭目录
closedir(dp_name);
//定义一个存储文件属性的结构体
struct stat file_info = {0};
//char *path_name = "usr_data";//目录名
//char *path_name = "1.txt";//文件名
//通过函数stat将文件的属性存储在结构体变量file_info
//stat(path_name,&file_info);
stat(argv[1],&file_info);
//判断普通文件
if(S_ISREG(file_info.st_mode))
printf("it is a regular file\n");
//判断目录文件
if(S_ISDIR(file_info.st_mode))
printf("it is a directory\n");
return 0;
}