系统文件IO

接口介绍

open(man 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: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。
参数:
    O_RDONLY: 只读打开
    O_WRONLY: 只写打开
    O_RDWR : 读,写打开
    这三个常量,必须指定一个且只能指定一个

    O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
    O_APPEND: 追加写


返回值:
    成功:新打开的文件描述符
    失败:-1

mode_t

open 函数具体使用哪个,和具体应用场景相关,如目标文件不存在,需要open创建,则第三个参数表示创建文件 的默认权限,否则,使用两个参数的open。

open函数返回值

在认识返回值之前,先来认识一下两个概念: 系统调用 和 库函数 

上面的 fopen fclose fread fwrite 都是C标准库当中的函数,我们称之为库函数(libc)。 而 open close read write lseek 都属于系统提供的接口,称之为系统调用接口 回忆一下我们讲操作系统概念时,画的一张图

文件描述符fd

通过对open函数的学习,我们知道了文件描述符就是一个小整数 0 & 1 & 2

Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0, 标准输出1, 标准错误2。

0,1,2对应的物理设备一般是:键盘,显示器,显示器 所以输入输出还可以采用如下方式:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

int main()
{
    char buf[1024];
    ssize_t s = read(0, buf, sizeof(buf));
    if(s > 0){
        buf[s] = 0;
        write(1, buf, strlen(buf));
        write(2, buf, strlen(buf));
    }
    return 0;
}

fcntl函数,也就是file control,提供了对文件描述符的各种操作。

ioctl()是底层的系统调用(system call),所以跨平台特性不好。

而fcntl则是被封装的函数,各个OS都是支持的。

read函数

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
// ssize_t 是有符号整数类型;size_t是无符号整数类型 

参数:

fd:文件描述符(文件名或文件路径)

buf:存放输入数据的内存缓冲区地址

count:指定最多能读取的字节数

返回值:

读取成功:返回的是读取到的字节数

读取到文件尾:0

读取失败:-1

write函数 

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);

参数:

与read()函数类似

fd:文件描述符(文件名或文件路径)

buf:要写入文件中数据的内存地址

count:从 buf 写入文件的数据字节数

返回值:

写入成功:返回 实际写入的字节数    

写入失败:-1

 而现在知道,文件描述符就是从0开始的小整数。当我们打开文件时,操作系统在内存中要创建相应的数据结构来 描述目标文件。于是就有了file结构体。表示一个已经打开的文件对象。而进程执行open系统调用,所以必须让进 程和文件关联起来。每个进程都有一个指针*files, 指向一张表files_struct,该表最重要的部分就是包涵一个指针数组,每个元素都是一个指向打开文件的指针!所以,本质上文件描述符就是该数组的下标。所以,只要拿着文件描述符,就可以找到对应的文件。

 文件描述符的分配规则

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

int main()
{
    int fd = open("myfile", O_RDONLY);
    if(fd < 0){
        perror("open");
        return 1;
    }
    printf("fd: %d\n", fd);
    close(fd);
    return 0;
}

perror函数

void perror(const char *str);

参数:

str -- 这是 C 字符串,包含了一个自定义消息,将显示在原本的错误消息之前。

该函数没有返回值

运行结果

关闭0或者2 

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

int main()
{
    close(0);
    //close(2);
    int fd = open("myfile", O_RDONLY);
    if(fd < 0){
        perror("open");
        return 1;
    }
    printf("fd: %d\n", fd);
    close(fd);
    return 0;
}

发现是结果是: fd: 0 或者 fd 2 可见,文件描述符的分配规则:在files_struct数组当中,找到当前没有被使用的 最小的一个下标,作为新的文件描述符。

重定向

那如果关闭1呢?看代码:

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

int main()
{
     close(1);
     int fd = open("myfile", O_WRONLY|O_CREAT, 00644);
     if(fd < 0){
         perror("open");
         return 1;
     }
     printf("fd: %d\n", fd);
     fflush(stdout);
 
     close(fd);
     exit(0);
}

 此时,我们发现,本来应该输出到显示器上的内容,输出到了文件 myfile 当中,其中,fd=1。这种现象叫做输出 重定向。常见的重定向有: >,  >>,  <

那重定向的本质是什么呢?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值