一、整体大纲
二、相关函数
1. getcwd
- 函数作用:获取当前目录
- 头文件
#include <unistd.h>
- 函数原型
char *getcwd(char *buf, size_t size);
- 参数说明:
buf传出参数,路径
size缓冲区大小
- 返回值
成功:返回路径的指针
失败:返回NULL
2. chdir
- 函数作用:改变工作路径
- 头文件
#include <unistd.h>
- 函数原型
int chdir(const char *path);
- 函数参数:
path对应的目标工作路径
- 返回值
成功:返回0
失败:返回-1,设置errno
注意:改变工作路径-注意属于进程独有。
示例:
chdir示例
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<sys/types.h>
4 #include<sys/stat.h>
5 #include<fcntl.h>
6
7 int main(int argc, char *argv[])
8 {
9 if (argc != 2)
10 {
11 printf("./a.out filename\n");
12 return -1;
13 }
14
15 //先切换工作目录
16 chdir(argv[1]);
17
18 int fd = open("temp.txt", O_WRONLY|O_CREAT, 0666);
19 write(fd, "daociyiyou", 10);
20 close(fd);
21
22 //获取当前工作目录
23 char buf[256] = {0};
24 getcwd(buf, sizeof(buf));
25 printf("buf is %s\n", buf);
26
27 return 0;
28 }
3. mkdir
- 函数作用:创建目录
- 头文件
#include <sys/stat.h>
#include <sys/types.h>
- 函数原型
int mkdir(const char *pathname, mode_t mode);
- 参数说明:
pathname创建的目录路径
mode目录权限 (mode & ~umask & 01777),注意权限,如果目录没有可执行权限,不可进入
- 返回值
成功:返回0
失败:返回-1,设置errno
4. rmdir
- 函数作用:只能删除空文件夹
5. opendir
- 函数作用:打开目录
- 头文件
#include <sys/types.h>
#include <dirent.h>
- 函数原型
DIR *opendir(const char *name);
- 参数说明:
pathname打开的目录
- 返回值
成功:返回指向该目录流的指针
失败:返回-1,设置errno
6. readdir
- 函数作用:读目录
- 头文件
#include <dirent.h>
- 函数原型
struct dirent *readdir(DIR *dirp);
- 参数说明:
dirp传入参数,opendir返回的指针
- 返回值
成功:读到目录项的内容
失败:NULL代表读到末尾或者有错误
struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* not an offset; see NOTES */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file; not supported by all file system types */
char d_name[256]; /* filename */
};
7. closedir
- 函数作用:关闭目录
- 头文件
#include <sys/types.h>
#include <dirent.h>
- 函数原型
int closedir(DIR *dirp);
- 函数参数:
dirp传入参数,opendir返回的指针
- 返回值
成功:返回0
失败:返回-1,设置errno
需求:统计一下指定目录下的文件个数?
统计指定目录下文件个数
1 #include <stdio.h>
2 #include<unistd.h>
3 #include<dirent.h>
4 #include<string.h>
5 #include <sys/types.h>
6
7 int count = 0;
8
9 int DirCount(char *dirname)
10 {
11 printf("================dirname:%s================\n", dirname);
12 //打开目录
13 DIR *dirp = opendir(dirname);
14 if (NULL == dirp)
15 {
16 perror("opendir err:");
17 return -1;
18 }
19 //循环读目录,如果是普通文件,count++,如果是目录,继续调用DirCount
20 struct dirent *dentp = NULL;
21 while ((dentp = readdir(dirp)) != NULL)
22 {
23 if (dentp->d_type == DT_DIR) //如果是目录
24 {
25 if (strcmp(dentp->d_name, ".") == 0 || strcmp(dentp->d_name, "..") == 0)
26 {
27 continue;
28 }
29 printf("================dirname:%s, dtype:%d================\n", dentp->d_name, dentp->d_type);
30 //注意进程的工作路径,不能直接打开子目录
31 //使用dirname拼接下一级子目录
32 char newdirname[256] = {0};
33 sprintf(newdirname, "%s/%s", dirname, dentp->d_name);
34 DirCount(newdirname);
35 }
36 if (dentp->d_type == DT_REG)
37 {
38 count++;
39 printf("-------------filename:%s, dtype:%d------------\n", dentp->d_name, dentp->d_type);
40 }
41 }
42 //关闭目录
43 closedir(dirp);
44 return 0;
45 }
46
47 int main(int argc, char *argv[])
48 {
49 if (argc != 2)
50 {
51 printf("./a.out dirname\n");
52 return -1;
53 }
54 DirCount(argv[1]);
55 printf("total file count %d\n", count);
56
57 return 0;
58 }
8. dup2
- 函数作用:文件描述符重定向
- 头文件
#include <unistd.h>
- 函数原型
int dup2(int oldfd, int newfd);
- 参数说明:
关闭newfd对应的文件描述符,将newfd重新指向为old对应的文件
- 返回值
成功:返回0
失败:返回-1,设置errno
9. dup
- 函数作用:复制文件描述符
- 头文件
#include <unistd.h>
- 函数原型
int dup(int oldfd);
- 参数说明:
新返回一个文件描述符指向oldfd对应的文件
- 返回值
成功:返回0
失败:返回-1,设置errno
需求:在代码中执行2次printf("hello world\n");一次输出到hello文件,后一次输出到屏幕上?
需求实现
1 #include <stdio.h>
2 #include<unistd.h>
3 #include<sys/types.h>
4 #include<sys/stat.h>
5 #include<fcntl.h>
6
7 int main(int argc, char *argv[])
8 {
9 if (argc != 2)
10 {
11 printf("./a.out filename\n");
12 return -1;
13 }
14 //先备份现场
15 int outfd = dup(1);
16 //先做重定向
17 int fd = open(argv[1], O_WRONLY|O_CREAT, 0666);
18 dup2(fd, 1);
19 printf("Hello world\n");
20 //必须刷新
21 fflush(stdout);
22
23 //需要回复1,重新对应标准输出
24 dup2(outfd, 1);
25 printf("Hello world\n");
26
27 close(fd);
28
29 return 0;
30 }
10. errno
- 函数作用:输出函数,根据errnum得到相应的错误信息
- 头文件
#include <string.h>
- 函数原型:
char *strerror(int errnum);
11. fcntl
- 改变已经打开的文件的属性
- 打开文件的时候: 只读
- 修改文件的: 添加追加 O_APPEND
三、补充
1. 索引节点inode
保存的其实是实际的数据的一些信息,这些信息称为“元数据”(也就是对文件属性的描述)。例如:文件大小,设备标识符,用户标识符,用户组标识符,文件模式,扩展属性,文件读取或修改的时间戳,链接数量,指向存储该内容的磁盘区块的指针,文件分类等等。( 注意数据分成:元数据+数据本身 )
注意inode怎样生成的:每个inode节点的大小,一般是128字节或256字节。inode节点的总数,在格式化时就给定(现代OS可以动态变化),一般每2KB就设置一个inode。一般文件系统中很少有文件小于2KB的,所以预定按照2KB分,一般inode是用不完的。所以inode在文件系统安装的时候会有一个默认数量,后期会根据实际的需要发生变化。
注意inode号:inode号是唯一的,表示不同的文件。其实在Linux内部的时候,访问文件都是通过inode号来进行的,所谓文件名仅仅是给用户容易使用的。当我们打开一个文件的时候,首先,系统找到这个文件名对应的inode号;然后,通过inode号,得到inode信息,最后,由inode找到文件数据所在的block,现在可以处理文件数据了。
2. inode和文件的关系
当创建一个文件的时候,就给文件分配了一个inode。一个inode只对应一个实际文件,一个文件也会只有一个inode。inodes最大数量就是文件的最大数量。