系统调用IO接口

  • 文件描述符:是一个非负数-操作文件的句柄,其实就是内核中一个进程打开的文件描述信息表的下标,通过这个下标可以在内核中找到相应的文件描述信息,通过这个描述信息实现文件操作
    在这里插入图片描述
    打开一个文件如果不操作了一定要关闭释放资源;文件描述符是有限的;若不关闭文件,文件描述符用光,则在进程中就打不开新文件了

在这里插入图片描述
由上图可以看到文件描述符是从3开始的,为什么呢?
一个程序运行起来,进程会默认打开三个文件:标准输入-0 / 标准输出-1 / 标准错误-2
文件描述符分配规则:最小未使用
代码说明:

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>

int main()
{
        close(0);//关闭0号描述符
        umask(0);
        int fd=open("./test.txt",O_RDWR|O_CREAT,0664);
        if(fd<0){
                perror("open error");
                return -1;
        }
        printf("%d\n",fd);

        close(fd);
}

在这里插入图片描述
close(0);关闭了标准输入,根据文件描述符分配规则,此时test.txt的文件描述符就变成了0
在这里插入图片描述

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>

int main()
{
        close(1);//关闭1号描述符
        umask(0);
        int fd=open("./test.txt",O_RDWR|O_CREAT,0664);
        if(fd<0){
                perror("open error");
                return -1;
        }
        printf("%d\n",fd);
        fflush(stdout);//刷新标准输出缓冲区
        
        close(fd);
}

啥也没的
在这里插入图片描述
打开test.txt有打印内容
在这里插入图片描述

close(1);关闭标准输出,printf函数是打印数据到标准输出,而此时标准输出关闭了,打开新文件后,printf并没有把数据打印出来,而是刷新缓冲区后,将数据写入到了文件中。这就是重定向的原理,即将数据不再写入原本文件,而是写入新的指定的文件中,实现方式就是替换这个描述符对应的文件描述信息;实际上是描述符的重定向,改变描述符所指向的文件,就改变了数据的流向
在这里插入图片描述

  • int dup2(int oldfd,int newfd);//描述符重定向
    让newfd这个描述符也指向oldfd所指向的文件,这时候oldfd和newfd都能操作oldfd所指向的文件
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>

int main()
{
        //close(1);//关闭1号描述符
        umask(0);
        int fd=open("./test.txt",O_RDWR|O_CREAT,0664);
        if(fd<0){
                perror("open error");
                return -1;
        }
        dup2(fd,1);//将1重定向到test.txt这个文件
        printf("fd=%d\n",fd);
        fflush(stdout);//刷新标准输出缓冲区

        close(fd);
}

啥也没的
在这里插入图片描述
打开test.txt文件有打印内容
在这里插入图片描述

系统IO调用接口

  1. int open( char *filename , int flag , mode_t mode);

1)相关解读

  1. 参数:(要打开的文件名称,选项,权限)
  2. flag :选项参数 打开方式
    必选项(只能选择其一):
    O_RDONLY :只读
    O_WRONLY :只写
    O_RDWR :读写
    可选项:
    O_CREAT :文件存在则打开,不存在则创建
    O_EXCL与O_CREAT同时使用(O_CREAT|O_EXCL):文件存在则报错,不存在则创建
    O_TRUNC:打开文件的同时清空原有内容
    O_APPEND:追加写,总是将数据写入到文件末尾
  3. mode :权限,八进制数字形式
    注意:如果使用了O_CREAT有可能创建新文件,一定要指定文件权限
  4. 返回值:一个非负整数-文件描述符-文件的操作句柄;失败返回-1

2)代码测试:

#include<stdio.h>
#include<fcntl.h>
#include<string.h>
#include<unistd.h>

int main()
{
        int fd=-1;
        fd=open("./test.txt",O_RDWR);
        if(fd<0){
                perror("open error");
                return -1;
        }

        close(fd);
        return 0;
}

  • [ test.txt文件删除后运行会打开失败]
    在这里插入图片描述
int main()
{
        int fd=-1;
        fd=open("./test.txt",O_RDWR|O_CREAT);//二进制操作
        if(fd<0){
                perror("open error");
                return -1;
        }

        close(fd);
        return 0;
}

  • [ 此时test.txt没有设置权限,权限是随机值]

在这里插入图片描述

int main()
{
        int fd=-1;
        umask(0);//将当前进程的文件创建权限掩码设置为0,这样的话,我们底下的权>限设置为多少就是多少,否则,最终文件权限=设置权限&~umask(0002);仅当前进程有效
        fd=open("./test.txt",O_RDWR|O_CREAT,0777);//二进制操作
        if(fd<0){
                perror("open error");
                return -1;
        }

        close(fd);
        return 0;
}
  • [ 设置完权限之后]

在这里插入图片描述

int main()
{
        int fd=-1;
        umask(0);//将当前进程的文件创建权限掩码设置为0,这样的话,我们底下的权>限设置为多少就是多少,否则,最终文件权限=设置权限&~umask(0002)
        fd = open("./test.txt",O_RDWR|O_CREAT|O_EXCL,0777);//二进制操作
        if(fd<0){
                perror("open error");
                return -1;
        }

        close(fd);
        return 0;
}

  • [ 验证O_CREAT|O_EXCL,此时test.txt存在,所以会报错]

在这里插入图片描述

  1. ssize_t write(int fd , char *buf , size_t count);
    1)相关解读
  1. ssize_t:有符号32位整数
  2. 参数
    fd:open返回的文件描述符-文件操作句柄,,通过fd指定要往哪个文件写入数据
    buf:要写入文件的数据的空间首地址
    count:要写入的数据大小
  3. 返回值:返回实际写入文件的数据字节长度,错误返回-1

2)代码测试

int main()
{
        int fd=-1;
        umask(0);//将当前进程的文件创建权限掩码设置为0,这样的话,我
们底下的权限设置为多少就是多少,否则,最终文件权限=设置权限&~umask(0002)
        fd = open("./test.txt",O_RDWR|O_CREAT,0777);//二进制操作
        if(fd<0){
                perror("open error");
                return -1;
        }

        char *ptr="You are so cute!\n";
        int ret=write(fd,ptr,strlen(ptr));
        if(ret<0){
                perror("write error");
                return -1;
        }
        printf("ret:%d\n",ret);

        close(fd);
        return 0;
}

在这里插入图片描述

  1. ssize_t read(int fd , char *buf , size_t count);
  1. 参数
    fd:open返回的文件描述符-文件操作句柄,,通过fd指定要往哪个文件写入数据
    buf:从文件中读取数据放到哪块缓冲区的首地址
    count:想要读取的数据长度,注意这个count不能大于缓冲区的大小
  2. 返回值:返回实际读取到的数据字节长度;错误返回-1
  1. off_t lseek( int fd , off_t offset , int whence );
  1. 参数
    off_t理解为int就行
    fd :open返回的文件描述符
    offset:偏移量
    whence:从哪里开始偏移
    SEEK_SET:文件起始位置;SEEK_CUR:文件当前读写位置;SEEK_END:文件末尾
  2. 返回值:成功返回当前位置相对于起始位置的偏移量;失败返回-1
  1. int close( int fd );
    通过文件描述符关闭文件,释放资源

代码测试:

int main()
{
        int fd=-1;
        umask(0);//将当前进程的文件创建权限掩码设置为0,这样的话,我
们底下的权限设置为多少就是多少,否则,最终文件权限=设置权限&~umask(0002)
        fd = open("./test.txt",O_RDWR|O_CREAT,0777);//二进制操作
        if(fd<0){
                perror("open error");
                return -1;
        }

        lseek(fd,0,SEEK_END);//目的读写位置跳转到文件末尾

        char ptr[1024] ="You are so cute!\n";
        int ret=write(fd,ptr,strlen(ptr));
        if(ret<0){
                perror("write error");
                return -1;
        }
        printf("ret:%d\n",ret);

        lseek(fd,0,SEEK_SET);//跳转到文件起始位置开始读取
        char buf[1024]={0};
        ret=read(fd,buf,1024);
        if(ret<0){
				perror("read error");
                return -1;
        }
        printf("ret:%d-[%s]\n",ret,buf);

        close(fd);
        return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值