Linux提供的文件操作类的系统调用接口
open/close(映射和注销)
read/write
lseek
Linux提供的文件系统操作类系统调用接口
stat
acces
chown/chmod
flock
link/symlink/unlink
mkdir/chdir/opendir/readdir
文件IO的注册与注销
1、如何创建空文件
文件描述符的获取: open() /create()
- open()和create()调用成功返回文件描述符,失败返回-1,并设置errno
- open()和create()调用返回的文件描述符一定是最小的未用描述符数字
- create()等价于open(pathname,O_CREAT|O_WRONLY|O_TRUNC,mode)
- open()可以打开设备文件,但是不能创建设备文件,设备文件必须使用mknod()创建
这些函数完成的是将内核驱动跟用户空间中的文件描述符建立映射关系
实验:
int main() {
int fd;
fd = open("a.txt",O_CREAT | O_RDWR ,0666);
if (fd == -1){
perror("open");
return -1;
}
// getchar();
// printf("Hello, World!\n");
write(fd,"Hello, World!",15);
close(fd);
return 0;
}
第一次执行得到的a.txt的内容为:
修改一下代码,再次执行:
int main() {
int fd;
fd = open("a.txt",O_CREAT | O_RDWR ,0666);
if (fd == -1){
perror("open");
return -1;
}
// getchar();
// printf("Hello, World!\n");
write(fd,"123",3);
close(fd);
return 0;
}
请问:此时的a.txt里面是什么?
A.123
B.123Hello, World!
C.Hello, World!123
D.Hello, World!
正确答案:E:123lo, World!
执行结果:
解析:因为光标每次是首位开始写的
文件编译工具
工程管理器:
以前:通过Makefile来管理哪些 .c文件编译
Clion
自带的Cmake:cmakelists.txt 《=》类似于以前的Makefile
Clion的cmakelists.txt创建工程时会自动生成,如:
版本限制
cmake_minimum_required(VERSION 3.22)
工程名,以及工程使用的语言比如也可以增加为C、CPP、asm
project(ClionProject C)
设置一个变量,告诉我们当前使用的C的标准
set(CMAKE_C_STANDARD 99)
添加一个可执行文件 其中,前者表示生成的可执行文件,后者表示源文件
add_executable(ClionProject main.c)
编译后就会在当前工程目录看见一个可执行文件:
写文件案例实验:
/*
* 1、在Linux下创建一个新文件,可以使用open/create系统调用接口
* create实际是open的便捷写法,但缺乏灵活性,如果明确创建新文件,可以使用create
* 2、create的flags等价O_CREAT|O_WRONLY|O_TRUNC
* 3、如果文件存在,使用open打开,如果使用create,那么原文件内容将清除
*
* 思考题:
* 1、为什么程序设计0666或者0777,实际创建的文件权限可能不是这个值
* */
int lesson1() {
int fd;
fd = creat(NEW_FILE_NAME, 0666);
if (fd == -1) {
perror("open");
return -1;
}
printf("create new file success!\n");
close(fd);
return 0;
}
/*
* 1、如果文件不存在,直接open,将会报"No such file or directory"错误
* 2、文件是否存在,使用O_CREAT不会出错影响,但只要加上O_EXCL才会报错,这个选项一般用作单例进程使用
* 3、O_TRUNC代表文件内容清空,一般用于临时文件,只要打开就使用全新的内容
* */
int lesson2() {
int fd;
// fd = open(NEW_FILE_NAME, O_CREAT | O_RDWR, 0666);
fd = open(NEW_FILE_NAME, O_RDWR, 0666);
// fd = open(NEW_FILE_NAME, O_CREAT | O_EXCL | O_RDWR, 0666);
// fd = open(NEW_FILE_NAME, O_CREAT | O_TRUNC | O_RDWR, 0666);
if (fd < 0) {
perror("open");
return -1;
}
printf("open new file success!\n");
close(fd);
return 0;
}
int main()
{
lesson1();
return 0;
}
可以看到,此时,执行成功,在该目录下创建了文件
然后用vim 打开该文件,写入字符123并保存
可以看到最后显示该文件有4个字节,而实际只写入了3个字节
原因:vim创建打开的文件会自动添加一个换行符。
ps:
可以使用od命令:以二进制形式查看文件存储形式(看文件本身内容)
如果记不住了可以使用:od --help
如:od -t x tmp_new.txt
ps:1、2、3对应的16进制字符的ACSII码是31、32、33
但是这样看着是挤在一起的,x后面不跟是默认是4个一起,因此x后面加一个1,一个字符一个字符的来看
od -t x1 tmp_new.txt
再在tmp_new.txt文件中的123后面写一个中国会怎么样?
此时的字符数量变成了10个
再执行 od -t x1 tmp_new.txt
一个字用三个字符来表示
回到代码,在文件已经存在的情况再次执行代码:
没有报错,还是文件创建成功:
之前是10个,再次执行后又变成了0个
Creat()函数在原始文件存在的情况下仍然可以创建 是因为,create的flags是等价于:O_CREAT|O_WRONLY|O_TRUNC
O_CREAT:如果该文件不存在就创建,并用mode的参数值为其设置权限
O_WRONLY:可写的方式打开文件
O_TRUNC:如果文件已经存在,那么打开文件时先删除文件中原有数据
ps:参考数值权限:
对于某一个文件,Linux系统中分为三类处理的人:
1、文件和文件目录的拥有者:u-user
2、文件和文件目录拥有者所在的组的用户:g-Group
3、其他用户:o-Others
可以看到对于每一个文件都有:
这里主要说权限:
r: 只读、w: 写入、x: 可执行
-rw——- (即110 000 000,二进制对应10进制就为:6 0 0) 只有所有者才有读和写的权限,因此,代码为600
-rw-r–r– (644) 只有所有者才有读和写的权限,组群和其他人只有读的权限
-rwx—— (700) 只有所有者才有读,写,执行的权限
-rwxr-xr-x (755) 只有所有者才有读,写,执行的权限,组群和其他人只有读和执行的权限
-rwx–x–x (711) 只有所有者才有读,写,执行的权限,组群和其他人只有执行的权限
-rw-rw-rw- (666) 每个人都有读写的权限
-rwxrwxrwx (777) 每个人都有读写和执行的权限
继续回到实验:
有一种场景:文件不存在我就创建再打开,但是文件在每次打开时不能清空,此时creat()不能使用,只能用open()
先把当前目录下的tmp_new.txt删掉
选择 lesson2()再次执行代码
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#define NEW_FILE_NAME "/tmp/temp/tmp_new.txt"
/*
* 1、在Linux下创建一个新文件,可以使用open/create系统调用接口
* create实际是open的便捷写法,但缺乏灵活性,如果明确创建新文件,可以使用create
* 2、create的flags等价O_CREAT|O_WRONLY|O_TRUNC
* 3、如果文件存在,使用open打开,如果使用create,那么原文件内容将清除
*
* 思考题:
* 1、为什么程序设计0666或者0777,实际创建的文件权限可能不是这个值
* */
int lesson1() {
int fd;
fd = creat(NEW_FILE_NAME, 0666);
if (fd == -1) {
perror("open");
return -1;
}
printf("create new file success!\n");
close(fd);
return 0;
}
/*
* 1、如果文件不存在,直接open,将会报"No such file or directory"错误
* 2、文件是否存在,使用O_CREAT不会出错影响,但只要加上O_EXCL才会报错,这个选项一般用作单例进程使用
* 3、O_TRUNC代表文件内容清空,一般用于临时文件,只要打开就使用全新的内容
* */
int lesson2() {
int fd;
fd = open(NEW_FILE_NAME, O_CREAT | O_RDWR, 0666);
// fd = open(NEW_FILE_NAME, O_RDWR, 0666);
// fd = open(NEW_FILE_NAME, O_CREAT | O_EXCL | O_RDWR, 0666);
// fd = open(NEW_FILE_NAME, O_CREAT | O_TRUNC | O_RDWR, 0666);
if (fd < 0) {
perror("open");
return -1;
}
printf("open new file success!\n");
close(fd);
return 0;
}
int main()
{
lesson2();
return 0;
}
重新生成了该文件
然后再在该文件中写上123
然后再次运行代码:
这里只使用O_RDWR参数
fd = open(NEW_FILE_NAME, O_RDWR, 0666);
删除文件,再次执行该种参数下的open函数:
总结:如果没有文件,使用open时应该加上O_CREAT参数,该参数可以保证每次运行文件都是空的.
再修改open函数的参数为:
fd = open(NEW_FILE_NAME, O_CREAT | O_EXCL | O_RDWR, 0666);
再次运行:
第一次运行结果:
创建成功!
第二次运行:
报错