系统IO编程

简介: 系统IO编程

常用函数

  • open(文件名,文件模式[, 文件权限]), 返回值是文件描述符
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags); // 多个flag用|连接,eg: flag1|falg2|...
int open(const char *pathname, int flags, mode_t mode);
flag 描述
O_RDONLY 只读
O_WRONLY 只写
O_RDWR 可读可写
O_CREAT 如果文件不存在就建立
O_EXCL 与CREAT合用,用户建立文件(原子操作)
O_APPEND 追加模式,将指针移动到文件末尾
O_DSYNC 效果是每次write后将内核缓冲区的数据立即写入磁盘
O_SYNC 效果是每次write后将内核缓冲区的数据和元数据写入磁盘
mode 说明
S_IRUSR 允许文件所属者读文件
S_IWUSR 允许文件所属者写文件
S_IXUSR 允许文件所属者执行文件
S_IRWXU 允许文件所属者读、写、执行文件
S_IRGRP 允许同组用户读文件
S_IWGRP 允许同组用户写文件
S_IXGRP 允许同组用户执行文件
S_IRWXG 允许同组用户读、写、执行文件
S_IROTH 允许其他用户读文件
S_IWOTH 允许其他用户写文件
S_IXOTH 允许其他用户执行文件
S_IRWXO 允许其他用户读、写、执行文件
S_ISUID set-user-ID(特殊权限)
S_ISGID set-group-ID(特殊权限)
S_ISVTX sticky(特殊权限)
  • mode可直接使用数字型,xxxx(S-U-G-O),方便些
  • close(文件描述符)
#include <unistd.h>
int close(int fd);

read(文件描述符,首地址,读取大小),每次读是从内核缓冲区读取的

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

write(文件描述符, 首地址,写入大小),先写入内核缓冲区

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

lseek(文件描述符,偏移量,参照位置)

#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
  • whence:
  • SEEK_SET: 文件头部
  • SEEK_CUR: 当前位置
  • SEEK_END: 文件结尾
#include<unistd.h>
#include<fcntl.h>
int fcntl(int fd, int cmd, .../* arg */) 

fd:文件描述符。

cmd:操作命令。此参数表示我们将要对 fd 进行什么操作,cmd 参数支持很多操作命令,可以打开 man 手册查看到这些操作命令的详细介绍,这些命令都是以 F_XXX 开头的,譬如 F_DUPFD、F_GETFD、F_SETFD 等,不同的 cmd 具有不同的作用,cmd 操作命令大致可以分为以下 5 种功能:


复制文件描述符(cmd=F_DUPFD 或 cmd=F_DUPFD_CLOEXEC);

获取/设置文件描述符标志(cmd=F_GETFD 或 cmd=F_SETFD);文件权限标志(O_RDONLY、O_WRONLY、O_RDWR)以及文件创建标志(O_CREAT、O_EXCL、O_NOCTTY、O_TRUNC)不能被设置、会被忽略;

获取/设置文件状态标志(cmd=F_GETFL 或 cmd=F_SETFL);

获取/设置异步 IO 所有权(cmd=F_GETOWN 或 cmd=F_SETOWN);

获取/设置记录锁(cmd=F_GETLK 或 cmd=F_SETLK);

其他知识点

  • fsync(), 将参数fd所指的文件内容和元数据写入磁盘。
#include <unistd.h>
  int fsync(int fd);

fdatasync(), 将参数fd所指的文件内容写入磁盘,

#include <unistd.h>
 int fdatasync(int fd);
  • sync(), 将所有的文件IO内核缓冲区的文件内容数据和元数据更新到磁盘。
#include <unistd.h>
   void sync(void);

以上所介绍的文件IO操作函数发生错误时会返回错误返回值-1。但我们并不能知道具体是啥错误,可喜的是以上函数发生错误时,系统会将一个全局变量errno置为错误代码(需要头文件<errno.h>)。

但它任然是一个错误代码,需要去查资料解析他的意思。有二个个函数可以帮我们解析,

  • char *strerror(int errno), 返回对应错误的字符指针(<sting.h>)
  • void perror(char *s), 直接答应错误,不需要传递参数errno,需要传递补充的提示信息(可不传)(<stdio.h>)
  • 空洞文件, 当lseek()到大于该文件的位置是也是可以读写的,不会报错(应用: 多线程同时操作文件,就像修公路一样,每个队伍修一部分)。但前后之间的不会占用实际物理空间。但在计算文件大小时是算在内的。

对同一个文件,可打开多次,但内核的缓冲区只有一个(动态文件)。静态文件:存储在硬件设备如磁盘,U盘等等存储设备。对于这些的读取是以块为单位的(一般为4K),也就是说不能单个字节单个字节的操作,故使用

  • 动态文件的方式即可加快读取时间,也可单个字节的方式操作文件。
  • 复制文件描述符(文件表没有复制



6423f72e52a74fa4b36a3d2538ab4855.png

  • int dup(int fd), 返回新的文件描述符,但文件表是同一个,
  • int dup2(int fd, int new_fd), new_fd为用户指定的新的描述符,如果已经存在就找一个比它的文件数字,返回新的文件描述符。

文件共享问题

当多个进程(线程)访问同一个文件时会出现竞争冒险的问题,因为进程的调度是不确定的,所以需要原子操作(将多个步骤合为一体,我猜是其内部实现了禁用中断,禁用调度器的调度)

  • O_APPEND, 将移动指针到末尾和写入数据组成了原子操作
  • O_EXCL|O_CREAT, 将检测文件是否存在和建立文件组成了原子操作
  • 函数,读写操作和偏移指针位置组成原子操作
#include <unistd.h>
ssize_t pread(int fd, void *buf, size_t count, off_t offset);
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);

直接IO读写: 绕过内核缓冲, mode加上O_DIRECT(还需要定义一个宏定义_GUN_SOURCE). eg:

 #define _GNU_SOURCE
  static char buf[8192] __attribute((aligned (4096)));  // 对齐
  fd = open(filepath, O_WRONLY|O_DIRECT);



目录
相关文章
|
2月前
|
数据采集 异构计算
LabVIEW编程LabVIEW开发高级数据采集技术 操作数字IO 例程与相关资料
LabVIEW编程LabVIEW开发高级数据采集技术 操作数字IO 例程与相关资料
62 22
|
3天前
|
Linux 数据处理 C语言
【Linux】基础IO----系统文件IO & 文件描述符fd & 重定向(下)
【Linux】基础IO----系统文件IO & 文件描述符fd & 重定向(下)
18 0
|
10天前
|
缓存 网络协议 算法
【Linux系统编程】深入剖析:四大IO模型机制与应用(阻塞、非阻塞、多路复用、信号驱动IO 全解读)
在Linux环境下,主要存在四种IO模型,它们分别是阻塞IO(Blocking IO)、非阻塞IO(Non-blocking IO)、IO多路复用(I/O Multiplexing)和异步IO(Asynchronous IO)。下面我将逐一介绍这些模型的定义:
|
19天前
|
Java 数据库连接
提升编程效率的利器: 解析Google Guava库之IO工具类(九)
提升编程效率的利器: 解析Google Guava库之IO工具类(九)
|
3天前
|
Linux C语言 C++
【Linux】基础IO----系统文件IO & 文件描述符fd & 重定向(上)
【Linux】基础IO----系统文件IO & 文件描述符fd & 重定向(上)
18 0
|
21天前
使用字节输入流报错 java.io.FileNotFoundException: srcdruid.properties (系统找不到指定的文件。)
使用字节输入流报错 java.io.FileNotFoundException: srcdruid.properties (系统找不到指定的文件。)
16 0
|
2月前
|
存储 Java API
Java语言IO(输入/输出)编程技术深度解析
Java语言IO(输入/输出)编程技术深度解析
257 1
|
1月前
|
调度 数据库 开发者
在Python编程中,并发编程和异步IO是两个重要的概念,它们对于提高程序性能和响应速度具有至关重要的作用
【6月更文挑战第10天】本文介绍了Python并发编程和异步IO,包括并发编程的基本概念如多线程、多进程和协程。线程和进程可通过threading及multiprocessing模块管理,但多线程受限于GIL。协程利用asyncio模块实现非阻塞IO,适合处理IO密集型任务。异步IO基于事件循环,能提高服务器并发处理能力,适用于网络编程和文件操作等场景。异步IO与多线程、多进程在不同任务中有各自优势,开发者应根据需求选择合适的技术。
22 0
|
2月前
|
移动开发 前端开发 JavaScript
uniapp中IO模块(管理本地文件系统)的常用功能封装
uniapp中IO模块(管理本地文件系统)的常用功能封装
159 1
|
2月前
|
安全 Linux vr&ar
【Linux 系统】基础 IO(动静态库)-- 详解
【Linux 系统】基础 IO(动静态库)-- 详解