文件系统管理
如果说将文件系统看成树形结构,那么文件夹就是分支节点,文件就是叶子节点。
Linux系统调用(System Call):就是 Linux 系统提供的一堆函数,只能用于 Linux 系统/Unix系统。
操作系统源码:https://www.kernel.org/
文件 I/O 相关函数:
- open:打开文件,如果成功就返回一个文件描述符(File Descriptor,就是一个非负整数,范围为:0 ~65535)
- close:关闭文件
- read
- write
- lseek:文件指针位置,可通过lseek改文件指针也可获取当前文件指针的位置
open函数
open函数参数详解:
(const char *pathname,int flags,mode_t mode);
fp = open(参数1,参数2,参数3);
参数1:代表文件路径及文件名
参数2:表示打开方式,根据man手册,flags有三个固定参数(宏):O_RDONLY 只读 、 O_WRONLY 只写 、 O_RDWR 可读可写。(没有文件不会自动创建)
另外还可以带上附加参数:
O_CREAT:若打开一个空文件,则会自动创建一个。
O_EXCL:配合O_CREAT使用,文件存在,则返回错误消息
O_APPEND:以追加方式打开,类似与C库中的fopen()函数参数a
O_NOCTTY:意为阻止文件作为打开控制终端。
O_TRUNC:文件存在,则清空文件;
参数3:mode,设置文件的权限 是八进制的权限码,但是起不到决定性的效果,最终权限为mode与~umask 按位与后得到的值(后续详解umask命令)。
三个特殊的文件描述符(fp):
- 0:标准输入文件
- 1:标准输出文件
- 2:标准错误文件(查找stdio.h文件
find / -name stdio.h 2>/dev/null
标准错误信息重定向到了null中 )
可变参数函数
int sum(int a, int b, int c) //函数参数是入栈存储,c地址最小,a地址最大,&a=&b+1=&c+2
{
printf("");
}
疑惑?(下例为何实现不了?)
/*
可变长参数函数声明
求任意个数的整数和
int sum(int n, ...); //此时n地址最大
通过第一个参数来推出后面的参数个数,此时n为后面参数个数
int sum(int n, ...)
{
int s = 0;
int i;
for(i = 0;i < n; i++)
{
s += *(&n - i - 1);
}
return s;
}
*/
//通过测试64位系统下:
//第一个参数为参数数量,以第一个参数为首地址,第二个参数距第一个参数28个字节,后续 + 8 个字节;
//按照这个逻辑首元素地址最低,且在栈顶,故栈低元素地址最高
int sum(int n, ...)
{
int s = 0;
int i;
for(i = 0;i < n; i++)
{
s += *(&n + 7 + i * 2);
}
return s;
}
//传统做法:
#include <stdarg.h>
int sum(int n, ...)
{
va_list vl;
va_start(vl, n);
int i;
int s = 0;
for(i = 0;i < n; i++)
{
s +=va_arg(vl, int);
}
va_end(vl);
}
umask命令
umask:设置新建文件的权限掩码,返回值为原来的掩码,默认掩码为002(Ubuntu 20.04)
在终端直接输入umask可以得到系统默认的文件权限掩码。
在open函数设置第三个参数时设置的mode & ~掩码 得到文件权限
例如:
mode = 0777 则 0777 & 775,则文件权限为:rwxrwxr-x
mode = 0123 则 0123 & 775,则文件权限为:–x-w—x
当然也可以自定义umask的值,但是只对当前进程有效
当设置umask(0);则默认掩码为 002。
则mode = 0777 则 0777 & 775,则文件权限为:rwxrwxrwx,满权限
cp命令实现
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char** argv)
{
int fd1,fd2;
int ret; //返回值
char buf[1024];//容器
fd1 = open(argv[1], O_RDONLY);
if(fd1 == -1)
{
perror("open fail");
return 1;
}
fd2 = open(argv[2],O_WRONLY | O_CREAT,0777);
if(fd2 == -1)
{
perror("open fail");
return 1;
}
while((ret = read(fd1, buf, sizeof(buf))) > 0)
{
write(fd2,buf,ret);//此时可判断write函数的返回值。
}
close(fd1);
close(fd2);
return 0;
}
Linux系统函数实现是无缓冲的读写操作,而标准C库函数中的文件 I/O 函数实现的是有缓冲的读写操作,其后者就是调用前者实现的,只不过增加了缓冲处理。
修改文件的属性信息函数:
- chmod:更改文件的权限
- chown:更改文件的所有者或组(通过用户id和组群id来改——getpwnam()通过用户名找用户信息)
- utime:修改文件的最近访问时间和最近修改时间
- truncate:裁剪文件
- rename:修改文件名
删除文件:remove(可删文件和非空文件夹),unlink(删文件),rmdir(删空文件夹)
创建文件夹:mkdir
创建链接文件:link (与ln命令对应)
硬链接的创建:ln oldfile newfile——link()函数
软链接的创建:ln -s old.dir soft.link.dir(带上-s即可)——symlink()函数
获取文件的属性信息:stat (与ls -la对应)
读取文件夹相关函数:opendir,readdir,closedir