1、文件的作用
linux下,一切均文件
2、linux的文件结构
root:该目录为系统管理员的用户主目录
bin:(binary)改目录存放最经常使用的命令
boot:存放启动Linux时使用的一些核心文件
dev:(device)存放Linux的外部设备,在Linux中访问设备的方式和访问文件的方式是相同的。
etc:所有的配置文件
home:用户的主目录,在Linux中每个用户都拥有自己的目录
var:存放着不断变化的文件数据,包含各种日志文件。
lib:存放着系统最基本的动态链接共享库,作用类似于Windows的dll文件。
usr:系统用户工具和程序
--bin:用户命令
--sbin:超级用户使用的
--include:标准头文件
--lib:库文件
--src:内核源代码
tmp:用于存在一些临时文件
media:linux系统会自动识别一些设备,例如U盘、光驱等,识别后,linux会把识别的设备挂载到改目录下。
mnt:临时挂载其他文件。
3、文件操作方式
(1)文件描述符 fd
是一个大于等于0的整数
每打开一个文件,就创建一个文件描述符,通过文件描述符来操作文件
预定义的文件描述符:
- 0:标准输入,对应于已打开的标准输入设备(键盘)
- 1:标准输出,对应于已打开的标准输出设备(控制台)
- 2:标准错误,对应于已打开的标准错误输出设备(控制台)
多次打开同一个文件,可得到多个不同的文件描述符
ps -ef # 查看进程信息
(2)使用底层文件操作(系统调用)
比如:read
可使用man 2 查看
(3)使用I/O库函数
比如:fread
可使用man 3 查看
4、底层文件操作(关于文件的系统调用)
1) write
(1)用法
man 2 write
(2)返回值
成功:返回实际写入的字节数
失败:返回-1 错误编号设置errno, 使用(strerror(errno))查看
注意:是从文件的当前指针位置写入!
文件刚打开时,文件的位置指针指向文件头
例子:
#include<stdio.h>
#include<stdlib.h>
int main(){
char buf[] = "hello world!\n";
// 写到标准输出stdout
write(1, buf, sizeof(buf));
// 写到标准错误stderror
write(2, buf, sizeof(buf));
return 0;
}
2) read
(1) 用法
man 2 read
(2) 返回值
> 0: 实际读取的字节数
0:已读到文件尾
-1:出错
注意:参数3表示最多能接受的字节数,而不是指一定要输入的字节数
例子:
#include<stdio.h>
#include<stdlib.h>
int main(){
char buffer[1024];
int cnt = 0;
cnt = read(0, buffer, sizeof(buffer));
write(1, buffer, cnt);
return 0;
}
3) open
(1) 用法
man 2 open
(2) 返回值
成功:文件描述符
失败:-1
(3) 打开方式
O_RDONLY 只读
O_WRONLY 只写
O_RDWR 读写
O_CREAT 如果文件不存在,则创建该文件,使用第三个参数进行权限设置,如果文件存在,则只打开文件
O_EXCL 如果同时使用O_CREAT而且该文件已经存在,则返回错误,用途:以防止多个进程同时创建。
O_APPEND 尾部追加方式(打开后,文件指针指向文件的末尾)
O_TRUNC 若文件存在,则长度被截为0,属性不变
例如 open("/dev/hello", O_RDONLY | O_CREAT | O_EXCL, 0777)
(4) 参数3(权限设置)
当使用O_CREAT时,使用参数3
S_I(R/W/X)(USR/GRP/OTH)
例如:S_IRUSR | S_IWUSR # 文件的所有者对该文件可读可写
(八进制表示法)0600
4) close
(1) 用法
man 2 close
终止指定文件描述符与对应文件之间的关联
并释放该文件描述符,即该文件描述符可被重新使用
(2) 返回值
成功返回0
失败返回1
示例:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#define FILE1 "./file1.txt"
#define FILE2 "./file2.txt"
#define LEN 4096
int main(){
int file1 = 0, file2 = 0;
char buffer[LEN];
int len = 0;
file1 = open(FILE1, O_RDONLY);
if(file1 < 0){
printf("open file1.txt failed, reason: %s! \n", strerror(errno));
}
file2 = open(FILE2, O_WRONLY | O_CREAT | O_EXCL, S_IRWXU);
if(file1 < 0){
printf("open file2.txt failed, reason: %s! \n", strerror(errno));
}
while((len = read(file1, buffer, sizeof(buffer))) > 0){
write(file2, buffer, len);
}
close(file2);
close(file1);
return 0;
}
5)time命令
观察耗时
time ./a.out
分别输出:
程序总的执行时间
该程序本身所消耗的时间(用户态所执行的时间)
系统调用所消耗的时间(内核态所执行的时间)
6) lseek
(1)用法
man 2 lseek
(2)返回值
成功:返回新的文件位置与文件头之间偏移
失败:-1
示例:从文件偏移量100的位置拷贝100个字节到另外一个文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#define FILE1 "./lseek_test.c"
#define FILE2 "./lseek_test2.c"
#define LEN 4096
int main(){
int file1 = 0, file2 = 0;
char buffer[LEN];
int len = 0, ret = 0;
file1 = open(FILE1, O_RDONLY);
if(file1 < 0){
printf("open file1.txt failed, reason: %s! \n", strerror(errno));
}
file2 = open(FILE2, O_WRONLY | O_CREAT | O_EXCL, S_IRWXU);
if(file1 < 0){
printf("open file2.txt failed, reason: %s! \n", strerror(errno));
}
# 改变文件的读写位置,基于SEEK_SET偏移100位置
ret = lseek(file1, 100, SEEK_SET);
printf("lseek ret: %d\n", ret);
len = read(file1, buffer, LEN);
printf("read[%d]:%s\n", len, buffer);
write(file2, buffer, len);
close(file2);
close(file1);
return 0;
}