其他分享
首页 > 其他分享> > 第二十八讲 IO 函数

第二十八讲 IO 函数

作者:互联网

第二十八讲 IO 函数

文章目录

本讲是联合几讲的内容,因为前面每一期内容都很少,所以结合起来了

本章会有一些扩展的知识,可能会有写偏差,但是会更详细一些,是参考了网上大佬们的理解。很感谢大佬们。

参考链接

一、 文件描述符和打开模式

1、常见文件操作函数

函数原型参数及其说明返回值头文件
open
(打开文件)
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:只在创建文件时需要,用于指定所创建文件的权限位(还要受到 umask 环境变量的影响)。
成功:文件描述符
失败:-1
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
close
(关闭文件)
int close(int fd)fd:文件描述符成功:0
失败:-1
#include <unistd.h>
read
(读取文件内容)
ssize_t read(int fd,void *buff,size_t count)fd:使用 open 打开的文件的文件描述符
buff:读取的文件内容
count:需要读取的长度
成功:
count:成功读取全部字节
0~count:
剩余文件长度小于count
读取期间被异步信号打断
失败:
-1,读取错误
#include <unistd.h>
write
(写入文件)
ssize_t write(int fd,void *buff,size_t count)fd:使用 open 打开的文件的文件描述符
buff:写入的文件内容
count:需要写入文件的长度
成功:
count:成功写入全部字节
0~count:
写入期间被异步信号打断
失败:
-1,读取错误
#include <unistd.h>
lseek
(设置文件读写位置)
off_t lseek(int fd,off_t offset,int where)fd:使用 open 打开的文件的文件描述符
offset:偏移量
where:偏移量基准点
成功:文件偏移位置值
失败:-1
#include <unistd.h>
sync
(页缓存和回写)
void sync(void);#include <unistd.h>

2、文件打开模式

选项说明
O_APPEND每次进行写操作时,内核都会先定位到文件尾,再执行写操作。
O_ASYNC使用异步 I/O 模式。
O_CLOEXEC在打开文件的时候,就为文件描述符设置 FD_CLOEXEC 标志。这是一个新的选项,用于解决在多线程下 fork 与用 fcntl 设置 FD_CLOEXEC 的竞争问题。某些应用使用 fork 来执行第三方的业务,为了避免泄露已打开文件的内容, 那些文件会设置 FD_CLOEXEC 标志。但是 fork 与 fcntl 是两次调用,在多线程下, 可能会在 fcntl 调用前,就已经 fork 出子进程了,从而导致该文件句柄暴露给子进程。关于 O_CLOEXEC 的用途
O_CREAT当文件不存在时,就创建文件
O_DIRECT对该文件进行直接 I/O,不使用 VFS Cache。
O_DIRECTORY要求打开的路径必须是目录
O_EXCL该标志用于确保是此次调用创建的文件,需要与 O_CREAT 同时使用; 当文件已经存在时,open 函数会返回失败。
O_LARGEFILE表明文件为大文件
O_NOATIME读取文件时,不更新文件最后的访问时间
O_NONBLOCK<br> O_NDELAY将该文件描述符设置为非阻塞的(默认都是阻塞的)
O_SYNC设置为 I/O 同步模式,每次进行写操作时都会将数据同步到磁盘,然后write 才能返回
O_TRUNC在打开文件的时候,将文件长度截断为0,需要与O_RDWR或O_WRONLY同时使用。在写文件时,如果是作为新文件重新写入,一定要使用O_TRUNC标志,否则可能会造成旧内容依然存在于文件中的错误,如生成配置文件、pid文件等

3、lseek where 参数说明

参数说明
SEEK_SET基准点为文件开头
SEEK_CUR基准点为当前位置
SEEK_END基准点为文件末尾

二、 标准 io 函数

c 标准库实现了一个 IO缓存区。通过调用标准io函数讲数据写入io缓存区,当数据达到一定数量或者调用fflush 函数才会将数据写入内核空间的页缓存区。同理,当页缓存区满了或者调用sync函数才能讲数据写入磁盘。他们的调用关系如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AOIgj9cX-1632844288613)(C:\Users\Dragon\Desktop\野火linux学习笔记\第一期\第二十八讲.assets\image-20210924232307432.png)]

1、 常见的标准io函数

函数说明
fopen打开文件
fclose关闭文件
fread读取文件
fwrite写入文件
fseek设置文件读写位置
fflush同步文件进入页缓冲区

2、文件io五大模式

模式说明
非阻塞模式当需要读写文件时,即使文件没法正常读写,也必须立马返回,不等待文件就绪
阻塞模式当需要读写文件时,文件没法正常读写时,等待文件就绪,然后进行正常读写
io多路复用IO多路复用主要有select、poll、epoll三种模式,select/poll相差不大,主要是通过轮询来不断的检测是否有描述符已就绪,select默认情况下支持最多监控1024个描述符,poll则没有这个限制(底层通过链表实现,可动态增加);epoll不是通过轮询,而是通过回调(callback)方式主动通知已有描述符已就绪,相比较select/poll效率有明显提升。
异步io读写文件的时候,只需要将数据发送过去,系统会将数据进行读写,然后发送信号告诉执行的读写状态
信号驱动io等待文件读写就绪状态,当文件就绪时,系统发送信号量通知用户可以读写文件,然后用户再进行读写

参考链接

三、控制 led 设备

1、驱动程序

本质

为硬件设备创建相应的设备节点文件;创建设备文件时,规定好设备文件的使用方式。

根据驱动程序规定的设备文件的使用方式去控制硬件。

步骤

1、找出硬件设备所对应的设备节点文件(/dev 或者 /sys 目录下)

2、找出驱动程序规定的设备文件的使用方式

四、实验代码(驱动红色led小灯)

/*
 * @LastEditors: 夜雨
 * @Date: 2021-09-26 22:23:56
 * @LastEditTime: 2021-09-28 23:10:02
 * @FilePath: /001led/operations_led.c
 */

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

#define LEDS_ROOT_PATH    "/sys/class/leds/"
#define LEDS_OPTION_FILE "/brightness"
#define LEDS_CUR_PATH(rootpath, color, operationfile)    ""rootpath""color""operationfile""
#define LEDS_PATH(color) LEDS_CUR_PATH(LEDS_ROOT_PATH, color, LEDS_OPTION_FILE)

int main(char* argc, char**argv)
{ 
    int redFd = open(LEDS_PATH("red"), O_WRONLY);
    {
        if(redFd == -1)
        {
            printf("open %s is failed",LEDS_PATH("red") );
            close(redFd);
            while(1);
        }
    }
    while(1)
    {
        write(redFd, "255", 3) ;
        printf("write 255\r\n" );
        sleep(1);
        write(redFd, "0", 1) ;
        printf("write 0\r\n" );
        sleep(1);
    }
    

    return 0;
}

五、 其他

本章讲到的所有函数并没有都将例子举出来,如果感兴趣,可以自己去实践下。当然,如果您仅仅只看文章,不去敲代码,其实是学不到什么东西的。并且这种要经常用才能加深自己的印象。

在实验代码中,我只做了红灯实验,感兴趣的可以将 open(LEDS_PATH("red"), O_WRONLY) 改成 open(LEDS_PATH("green"), O_WRONLY) 或者 open(LEDS_PATH("blue), O_WRONLY) 试试看其他灯的效果。如果你还想玩,可以改改亮灭函数控制不同灯亮的方法。

标签:文件,LEDS,第二十八,函数,int,读写,IO,include,open
来源: https://blog.csdn.net/qq_34355238/article/details/120539947