【Linux】系统调用的文件操作
文章目录
- 复习C文件IO操作
- 系统调用的文件操作
- open
- write
- read
- lseek
- close
- 文件描述符与文件流指针的关系
- 文件描述符
- 文件流指针
复习C文件IO操作
首先,复习一下C文件IO相关操作 ,参考之前的文章:
文件操作
系统调用的文件操作
open
int open(const char* filename,int falgs,mode_t mode)
参数解释:
filename:待打开的文件名称
flags:以何种方式打开。
必选项:三者任选其一,不能同时使用
—>O_RDWR:以读写模式打开;
—>O_RDONLY:以只读模式打开
—>O_WRONLY:以只写模式打开
可选项:可以选择多个,附加使用
—>O_CREAT:如果文件不存在,则创建文件
—>O_TRUNC:打开文件之后截断文件(清空文件)
—>O_APPEND:以追加方式打开
mode:对于新创建出来的文件,设置文件权限
返回值:返回文件描述符
代码实现:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
int ret=open("./linux84",O_RDWR|O_CREAT,0664);
if(ret<0)
{
perror("open");
return -1;
}
while(1)
{
sleep(1);
}
printf("file oper ret=%d\n",ret);//ret=3
return 0;
}
代码中问题1:为啥文件描述符(ret)是3?
首先,我们先查看进程pid:ps aux | grep [文件名]
接着,查看进程打开的文件资源:cd/proc/[pid]/fd
启动任何一个程序,启动的进程,都会打开三个文件描述符,分别是标准输入,标准输出,标准错误,分别对应图中蓝色0,1,2。所以,当程序新打开的文件描述符,就会依次往下排布,占用了3(少数情况)。一般情况,遵循最小未占用规则,就是文件描述符从小到大依次往下排,哪个位置没有被占用,新打开的文件就会占用哪个,比如0被关闭掉了,1、2还在,那新打开的文件就会占用0的位置,而不是3。
代码中问题2:打开模式,不同的宏在组合时为什么要按位或?
查看宏定义:
#define O_RDONLY 00 00000000
#define O_WRONLY 01 00000001
#define O_RDWR 02 00000010
#define O_CREAT 0100 0100000
//第一列表示八进制数,第二列表示二进制数
想让一个文件既读写,又不存在的时候可以创建
例如:O_RDWR | O_CREAT
用按位或就可以实现:
//00000010 读写
//01000000 创建
//01000010 按位或结果,左边第一个bit位为1,表示以读写方式打开;左边第6个bit位为1,表示文件不存在则创建
代码中问题3:0664是啥?
第一个0相当于8进制数字的起手式,相当于16进制的0x,后面数字为八进制数字,该数字含义是对新创建的文件设置文件权限。
可复习前面的文章:文件权限管理
write
ssize_t write(int fd,const void*buf,size_t count)
fd:文件描述符
buf:写入的数据
count:写入是数据大小
read
ssize_t read(int fd,void* buf,size_t count)
int ret=open("./linux84",O_RDWR|O_CREAT,0664);
char buf[10] = {
0};
read(ret,buf,sizeof(buf) - 1);
fd:文件描述符,从哪里去读
buf:读到哪里去(程序员在代码当中定义的缓冲区)
count:最大可以读多少字节。这里注意一定要预留\0的位置,否则会导致在访问buf的时候,越界访问,可能导致程序崩溃。
lseek
off_t lseek(int fd,off_t offset,int whence)
fd:需要操作的文件描述符
offset:偏移量
whence:偏移到哪里去
close
int close(int fd)
close(0);
int ret = -1;
ret = open("./linux84",O_RDWR|O_CREAT,0664);
if(ret<0)
{
return -1;
}
printf("file oper ret = %d\n",ret);
return 0;
fd:文件描述符。
如果一味的在程序当中打开文件,而不去关闭文件,最终会受到open files的限制
文件描述符与文件流指针的关系
fopen/fread/fwrite/fseek/fclose—>文件流指针—>C库当中的函数
open/read/write/lseek/close—>文件描述符—>系统调用函数
文件描述符
文件描述符就是一个正整数。
1.文件描述符就是内核当中维护的fd_array数组的下标,下标是从0开始的,所以文件描述符是一个正整数。
2.当程序员操作文件的时候,其实就是通过文件描述符,找到fd_array数组当中对应的元素,每一个元素都对应一个文件信息,内核通过操作数组元素对应的文件信息,找到对应的文件,从而实现文件操作。
文件流指针
typedef struct _IO_FILE FILE
文件流指针的本质是一个结构体,而这个结构体是struct _IO_FILE
1.在进程终止,刷新缓冲区,其实刷新的是C库当中维护的缓冲区,并非是内核当中维护的。
exit()—>刷新缓冲区—>C库函数
_exit()—>不会刷新缓冲区—>系统调用
2.当我们在使用文件流指针的时候,其实文件流指针对应的数据结构内容也保存了对应的文件描述符,当使用文件流指针进行读写的时候,其实也是C库当中操作文件描述符来完成读写的。
3.stdin,stdout,strerr每一个都对应一个struct _IO_FILE的结构体
还没有评论,来说两句吧...