当前位置:网站首页>第04天-文件IO

第04天-文件IO

2022-06-24 21:16:00 不虚此行-Rui

第04天-文件IO

在这里插入图片描述
在这里插入图片描述

01.系统调用简介和实现

系统调用是受控的内核入口,借助于这一机制,进程可以请求内核以自己的名义去执行某些动作

**实现:**系统调用是操作系统内核的一部分的,必须以某种方式提供给进程让他们去调用。

CPU可以在不同的特权级别下运行,而相应的操作系统也有的运行级别(用户态和内核态)运行在内核态的进程可以毫无限制的访问各种资源,

操作系统通过软件中断从用户态切换到内核态

02.系统调用和库函数的区别

库函数:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-18xZd0AJ-1656067116776)(D:\图片\image-20220624082305545.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jUqNl4V0-1656067116778)(D:\图片\image-20220624083042666.png)]

03.错误处理函数

errno是记录系统的最后一次错误代码,代码是一个int型,在errno.h中定义。当Linux C API函数发生异常时,一般会将

errno全局变量赋一个整数值,不同的值表示不同的含义,

#include<stdio.h>
#include<errno.h>
#include<string.h>
int main()
{
    
          FILE *fp=fopen("txt","r");
          if(NULL==fp)
          {
    
                  printf("%d\n",errno);//打印错误码
                  printf("%s\n",strerror(errno));
                  perror("fopen err");
          }
          return 0;
  }

结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QRKb6Lfs-1656067116778)(D:\图片\image-20220624091815191.png)]

一部分返回值代表的信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zuq2frC9-1656067116779)(D:\图片\image-20220624092904783.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tcsGb7zO-1656067116779)(D:\图片\image-20220624093031088.png)]

04.虚拟地址空间

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7SbINfYi-1656067116780)(D:\图片\image-20220624093903228.png)]

05.文件描述符

打开现存文件或新建文件时,系统会返回一个文件描述符,用来指定已打开的文件。相当于标号(操作文件描述符相当于操作描述指定的文件)

程序运行起来都有一张文件描述符的表,标准输入,输出,错误输出设备文件被打开,对应的文件描述符0,1,2记录在表中,默认被打开。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tfhpJDwa-1656067116780)(D:\图片\image-20220624105334278.png)]

06.文件IO函数

open函数:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

       int open(const char *pathname, int flags);
       int open(const char *pathname, int flags, mode_t mode);
功能:
   打开文件,如果文件存在则可以选择创建
参数:
    pathname:文件路径及文件名
    flags:打开文件的行为标志,必选项O_RDONLY(只读),O_WRONLY(只写),O_RDWR(可读,可写)
    mode:这个参数,只有在文件不存在时有效,指新建文件时指定文件的权限
返回值:
    成功:成功返回打开的文件描述符
    失败:-1

flags详细说明

必选

  • O_RDONLY—只读
  • O_WRONLY—只写
  • O_RDWR—可读,可写

可选项,和必选项按位或起来

O_CREAT 文件不存在则创建文件,使用此选项时需使用mode说明文件的权限

O_EXCL 如果同时指定了O_CREAT,且文件已经存在,则出错

O_TRUNC 如果文件存在,则清空文件内容

O_APPEND 写文件时,数据添加到文件末尾

O_NONBLOCK 对于设备文件,以O_NONBLOCK方式打开可以做非阻塞i/o

mode补充说明

1)文件最终权限:mode & -umask

2)shell进程的umask掩码可以用umask命令查看

umask:查看掩码

umask mode:设置掩码,mode为八进制

umask -S:查看各组用户的默认操作权限

close函数

#include<unistd.h>
int close(int fd)
功能:
   关闭已打开的文件
参数:
 fd:文件描述符,open()的返回值
返回值:
    成功:0
    失败: -1,并设置errno

open和close示例:

//以只写的方式打开,若存在则打开,如果文件不存在则直接创建
//fp=open("txt",O_WRONLY|O_CREAT,0644);
//如果文件存在就报错,不存在则创建
//fp=open("txt",O_WRONLY|O_CREAT|O_EXCL,0644);
//O_TRUNC 清空文件内容
//若不存在则创建,若存在打开后清空
//fp=open("txt",O_WRONLY|O_TRUNC|O_CREAT,0644);
//O_APPEND
//以只写的方式和追加的方式打开一个文件,如果文件不存在会报错
//fp=open("txt",O_WRONLY|O_APPEND);
//
if(fp==-1)
{
    
        perror("open");
        return 1;
}
      printf("fp=%d\n",fp);
      close(fp);
        return 0;
}

write函数

#include<unistd.h>
ssize_t write(int fd,const void *buf,size_t count)
功能: 把指定数目的数据写到文件
参数:
  fd:文件描述符
  buf:数据首地址
  count:写入数据的长度
返回值:
   成功:实际写入数据的字节个数
   失败:-1

示例:

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
int main(void){
    
//1.以只写的方式打开,若没有则创建
int fp=-1;
char *str="hello word";
fp=open("txt",O_WRONLY|O_CREAT,0644);
if(fp==-1)
{
    
        perror("open");
        return 1;
}
int ret=0;
//写文件
ret=write(fp,str,strlen(str));
if(ret==-1)
{
    
        perror("write");
        return 2;
}
printf("ret=%d\n",ret);
//3.关闭文件
close(fp);
        return 0;}

read函数:

#include<unistd.h>
ssize_t read(int fp,void *buf,size_t count)
功能:
   把指定数目的数据读到内存(缓冲区)
参数:
   fp:文件描述符
   buf:内存首地址
   count:读取的字节个数
返回值:
   成功:实际读取到的字节数
   失败:-1
int fp=-1;
char buf[128];
fp=open("txt",O_RDONLY);
if(fp==-1)
{
    
        perror("open");
        return 1;
}
int ret=0;
//读文件
//从文件描述符fp中最多读取size个字节保存到buf中,实际读取字节数通过返回值返回
ret=read(fp,buf,128);
if(ret==-1)
{
    
        perror("read");
        return 2;
}
printf("ret=%d,len=%s\n",ret,buf);
//3.关闭文件
close(fp);
        return 0;}

07.阻塞与非阻塞

读常规文件是不会阻塞的,不管读多少字节,read一定会在有限时间内返回,

从终端设备或网络读则不一定,如果从终端输入的数据没有换行符,调用read读终端设备就会阻塞,如果一直没有数据就一直阻塞。

lseek函数

#incldue<sys/types.h>
#include<unistd.h>
off_t lseek(int fd,off_t offset,int whence);
功能:
   改变文件的偏移量
参数:
  fd:文件描述符
  offset:根据whence来移动的位移数,正数右移,负数左移,超过文件开头则出错返回,如果向后移动超过文件末尾,再次写入时将增大文件尺寸。
  whence:其取值如下:
    SEEK_SET:从开头移动offset个字节
    SEEK_CUR:从当前位置移动offset个字节
    SEEK_END:从文件末尾移动offset个字节
返回值:
   若lseek成功执行,则返回新的偏移量
   如果失败,返回-1
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
int main()
{
    
        int fd=-1;
        int ret=-1;
        char  buf[128];
        //1.打开文件
        fd=open("txt",O_RDWR|O_CREAT,0644);
        if(fd==-1)
        {
    
                perror("open");
                return 1;
        }
        //2.lseek加write
        write(fd,"sundengrui",10);
        ret=lseek(fd,32,SEEK_SET);
        if(-1==ret)
        {
    
                perror("lseek");
                return -1;
        }
        write(fd,"12345678",9);
        //将文件位置指针指向开头
        lseek(fd,0,SEEK_SET);
        memset(buf,0,128);
        ret=read(fd,buf,128);
        printf("ret:%d\n,buf:%s\n",ret,buf);
        //3.关闭文件
        close(fd);
        return 0;
}

ror(“lseek”);
return -1;
}
write(fd,“12345678”,9);
//将文件位置指针指向开头
lseek(fd,0,SEEK_SET);
memset(buf,0,128);
ret=read(fd,buf,128);
printf(“ret:%d\n,buf:%s\n”,ret,buf);
//3.关闭文件
close(fd);
return 0;
}


原网站

版权声明
本文为[不虚此行-Rui]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_58389786/article/details/125450728