【Linux】系统调用的文件操作

复习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的结构体
在这里插入图片描述

©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页