UNIX文件类型主要包含如下几种:
1.普通文件(regular file)
2.目录文件(directory file)
3.块特殊文件(block special file),这种文件提供对设备(例如硬盘)带缓冲的访问,每次访问以固定长度为单位进行。
4.字符特殊文件(character special file),这种文件提供对设备不带缓冲的访问,每次访问长度可变。
5.FIFO文件,命名管道(named pipe),用于进程间通信。
6.socket文件,用于进程间的网络通信,也可以在同一台机器上进行进程间通信。
7.符号链接文件(symbolic link),指向另外一个文件。
文件类型信息存放在stat结构体的st_mode成员中。stat结构体的声明如下:
struct stat {
mode_t st_mode; //文件对应的模式,文件,目录等
ino_t st_ino; //inode节点号
dev_t st_dev; //设备号码
dev_t st_rdev; //特殊设备号码
nlink_t st_nlink; //文件的连接数
uid_t st_uid; //文件所有者
gid_t st_gid; //文件所有者对应的组
off_t st_size; //普通文件,对应的文件字节数
time_t st_atime; //文件最后被访问的时间
time_t st_mtime; //文件内容最后被修改的时间
time_t st_ctime; //文件状态改变时间
blksize_t st_blksize; //文件内容对应的块大小
blkcnt_t st_blocks; //文件内容对应的块数量
};
posix.1实现允许将进程间通信(IPC)对象表示为文件,下面的宏确定可用来确定IPC对象的类型。
上述宏的参数是结构体stat。
那么如何才能获取stat结构体呢,使用下面三个函数:
#include <sys/stat.h>
int stat(const char* restrict pathname, struct stat* restrict buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char* restrict pathname, struct stat* restrict buf );
//三个函数如果成功则返回0,出错返回-1.
lstat类似于stat,但是当文件时一个符号链接时,lstat获取的是该符号链接的有关信息,而不是该符号链接引用的
文件的信息。
实践:
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, char * argv[]){
struct stat buf;
if(argc != 2){
printf("you must specify one parameter.\n");
return -1;
}
if(stat(argv[1],&buf) < 0){
perror("stat");
return -1;
}
if(S_ISREG(buf.st_mode)){
printf("regular.\n");
}else if(S_ISDIR(buf.st_mode)){
printf("directory.\n");
}else if(S_ISBLK(buf.st_mode)){
printf("block.\n");
}else if(S_ISLNK(buf.st_mode)){
printf("symbolic link.\n");
}
return 0;
}
运行结果:
yan@yan-vm:~/apue$ ll /etc/init.d/acpid
lrwxrwxrwx 1 root root 21 Apr 12 20:33 /etc/init.d/acpid -> /lib/init/upstart-job*
yan@yan-vm:~/apue$ ./a.out /etc/init.d/acpid
regular.
如果将stat修改为lstat,结果如下:
yan@yan-vm:~/apue$ ll /etc/init.d/acpid
lrwxrwxrwx 1 root root 21 Apr 12 20:33 /etc/init.d/acpid -> /lib/init/upstart-job*
yan@yan-vm:~/apue$ ./a.out /etc/init.d/acpid
symbolic link.