ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

第二十八讲 IO 函数

2021-09-29 00:02:37  阅读:174  来源: 互联网

标签:文件 LEDS 第二十八 函数 int 读写 IO include open


第二十八讲 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 目录下)

  • led 设备节点文件目录

    /sys/class/leds

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

  • 往 brightness 文件写入数值

四、实验代码(驱动红色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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有