【Linux_Unix系统编程】chapter5 深入探究文件IO

Chapter5 深入探究文件I/O
本章节将介绍另一个与文件操作相关的系统调用:多用途的fcntl(),并展示其应用之一读取和设置打开文件的状态标志。

5.1 原子操作和竞争条件
所有系统调用都是以原子操作方式执行的。是以为内核保证了某系统调用中的所有步骤会作为独立操作而一次性加以执行,其间不会为其他进程或线程所中断。

以独占方式创建一个文件:
当同时制定O_EXCL与O_CREAT作为open()标志位时,如果要打开的文件已存在,则open()将返回一个错误。保证了进程是打开文件的创建者。

向文件尾部追加数据:
多个进程同时向同一个文件尾部添加数据。

5.2 文件控制操作:fcntl()
fcntl()系统调用对一个打开的文件描述符执行一系列控制操作。
#include <fcntl.h>
int fcntl(int fd, int cmd, …);

5.3 打开文件的状态标志
fcntl()的用途之一是针对一个打开的文件,获取或修改其访问模式和状态标识。
int flags, accessMode;
flags = fcntl(fd, F_GETFL);
if(flags = -1)
errExit(“fcntl”);
在上述代码之后,可以以如下代码测试文件是否以同步写方式打开:
if(flags & O_SYNC)
printf(“wirtes are synchronize\n”);

5.4 文件描述符和打开文件之间的关系
进程级的文件描述符表
系统级的打开文件表
文件系统的i-node表
5.5 复制文件描述符
dup()调用复制一个打开的文件描述符oldfd,并返回一个新描述符。二者指向同一打开的文件句柄。
#include <unistd.h>
int dup(int oldfd);

5.6 在文件特定偏移量处的I/O:pread()和pwrite()
系统第阿勇pread()和pwrite()完成与read和write()相似的工作,只是前两者会在offset参数所指定的位置进行文件IO操作,而非始于文件的当前偏移量楚,且他们不会修改文件的当前你偏移量。
#include <unistd.h>
ssize_t pread(int fd, void *buf, size_t count, off_t offset);
ssize_t pwirte(int fd, const void *buf, size_t count, off_t offset);

pread()调用等价于如下调用纳入同一原子操作:
off_t orig;
orig = lseek(fd, 0,SEEK_CUR);
lseek(fd, offset, SEEK_SET);
s = read(fd, buf, len);
lseek(fd, origin, SEEK_SET);

5.7 分散输入和集中输出(Scatter-Gather I/O):readv()和writev()
#include <sys.uio.h>
ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
ssize_t wirtev(int fd, const struct iovec *iov, int iovcnt);
这些系统调动并非只是对单个缓冲区进行读写操作,而是一次即可传输多个缓冲区。数组iov定义一组用来传输数据的缓冲区。整数iovcnt则指定了iov的成员个数。iov中的每个成员都是如下形式的数据结构。
struct iovec
{
void *iov_base;
size_t iov_len;
}

5.8 截断文件:truncate()和ftruncate()系统调用
truncate()和ftruncate()系统调用将文件打下设置为length参数指定的值。
#include <unistd.h>
int truncate(const char* pathname, off_t length);
int ftruncate(int fd, off_t length);
若文件当前长度大于参数length,调用将丢弃超出部分,若小于参数length,调用将在文件尾部添加一系列空字节或者是一个文件空洞。

5.9 非阻塞I/O
在打开文件是指定O_NONBLOCK标志,目的有二:
(1):若open()调用未能立即打开文件,则返回错误,而非陷入阻塞。
(2):调用open()成功后,后续的I/O操作也是非阻塞的。
管道,FIFO,套接字,设备都支持非阻塞模式。

5.10 大文件I/O
过渡性LFS API
要使用过渡性的LFS API,必须在编译程序时定义 LARGEFILE64_SOURCE功能测试宏。 fopen64(),open64(),lseek64(),truncate64(),stat64(),mmap64()和setrlimit64().
调用open64(),相当于在调用open()是指定O_LARGEFILE标志。

5.11 /dev/fd 目录
对于每个进程,内核都提供有一个特殊的虚拟目录/dev/fd.该目录中包含”/dev/fd/n”形式的文件名,其中n是与进程中的打开的文件描述符相对应的编号。例如:/dev/fd/0 就对应于进程的标准输入。
e.g.:如下等价,相当于复制相应的文件描述符。
fd = open(“/dev/fd/1”, O_WRONLY);
fd = dup(1)

5.12 创建临时文件
mkstemp()和tmpfile()
基于调用者提供的模板,mkstemp()函数生成一个唯一文件名并打开该文件,返回一个可用于I/O调用的文件描述符。
#include <stdlib.h>
int mkstemp(char *template);
模板参数采用路径形式,其中最有6个字符必须是XXXXXX。
int fd;
char template[] = “/tmp/somestringXXXXXX”;
fd = mkstemp(template);
if(fd == -1)
errExit(“mkstemp”);
unlink(template);

tmpfile()函数会创建一个名称唯一的临时文件,并以读写方式将其打开。
#include <stdio.h>
FILE *tmpfile(void);

时间: 2024-11-08 17:20:50

【Linux_Unix系统编程】chapter5 深入探究文件IO的相关文章

嵌入式 Linux系统编程(一)——文件IO

嵌入式 Linux系统编程(一)--文件IO 一.文件IO概念 linux文件IO操作有两套大类的操作方式:不带缓存的文件IO操作,带缓存的文件IO操作.不带缓存的属于直接调用系统调用(system call)的方式,高效完成文件输入输出.它以文件标识符(整型)作为文件唯一性的判断依据.这种操作不是ASCI标准的,与系统有关,移植有一定的问题.而带缓存的是在不带缓存的基础之上封装了一层,维护了一个输入输出缓冲区,使之能跨OS,成为ASCI标准,称为标准IO库.不带缓存的方式频繁进行用户态 和内核

嵌入式 Linux系统编程(二)——文件描述符控制函数fcntl

嵌入式 Linux系统编程(二)--文件描述符控制函数fcntl 由于fcntl函数实在过于灵活和复杂,本文将fcntl函数从文件IO中单独列出来,便于详细解读.函数原型如下: #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd, ... /* arg */ ); fcntl函数用于控制操作文件描述符fd,对文件描述符的控制操作由cmd控制命令来控制,arg参数为可选参数,是否需要arg参数取决于控制命令

嵌入式 Linux系统编程(三)——标准IO库

嵌入式 Linux系统编程(三)--标准IO库 与文件IO函数相类似,标准IO库中提供的是fopen.fclose.fread.fwrite等面向流对象的IO函数,这些函数在实现时本身就要调用linux的文件IO这些系统调用. 一.标准IO库函数的缓冲机制 由于IO设备的访问速度与CPU的速度相差好几个数量级,为了协调IO设备与CPU的速度的不匹配,对于块设备,内核使用了页高速缓存,即数据会先被拷贝到操作系统内核的页缓存区中,然后才会从操作系统内核的缓存区拷贝到应用程序的地址空间. 当应用程序尝

【Linux_Unix系统编程】Chapter4 文件IO

Chapter4 文件IO 4.1 概述 文件描述符 == Windows的句柄 标准文件描述符: 0 标准输入 STDIN_FILENO stdin 1 标准输出 STDOUT_FILENO stdout 2 标准错误 STDERR_FILENO stderr (1):fd = open(pathname, flags, mode) (2):numread = read(fd, buffer, count) (3):numwritten = write(fd, buffer, count) (

GPIO编程1:用文件IO的方式操作GPIO

概述 通过 sysfs 方式控制 GPIO,先访问 /sys/class/gpio 目录,向 export 文件写入 GPIO 编号,使得该 GPIO 的操作接口从内核空间暴露到用户空间,GPIO 的操作接口包括 direction 和 value 等,direction 控制 GPIO 方向,而 value 可控制 GPIO 输出或获得 GPIO 输入.文件 IO 方式操作 GPIO,使用到了4个函数 open.close.read.write. 首先,看看系统中有没有“/sys/class/

【Linux_Unix系统编程】chapter6 进程

chapter6 进程 重点关注进程虚拟内存的布局及内容.6.1 进程和程序 进程(process)是一个可执行程序(program)的实例. 程序是包含了一系列信息的文件,这些信息描述了如何在运行时创建一个进程,所包含的内容如下. (1):二进制格式标识:每个程序文件都包含用于描述可执行文件格式的元信息. (2):机器语言指令:对程序算法进行编码 (3):程序入口地址:标识程序开始执行时的起始指令位置. (4):数据:包含的变量初始值和程序使用的字面量值 (5):符号表以及重定位表:描述程序中

《UNIX环境高级编程》笔记——3.文件IO

一.引言 说明几个I/O函数:open.read.write.lseek和close,这些函数都是不带缓冲(不带缓冲,只调用内核的一个系统调用),这些函数不输入ISO C,是POSIX的一部分: 多进程共享资源(包括文件)时,会有很多额外的烦恼,需要对共享资源.原子操作等概念深入理解,需要理解涉及的内核有关数据结构,这些数据结构对理解文件.共享有重要作用: 最后介绍dup.fcntl.sync.fsync和ioctl函数. 二.文件描述符 open或creat文件时,内核--文件描述符fd-->

【Linux_Unix系统编程】Chapter8 用户和组

chapter8 用户和组 8.1 密码文件 /etc/passwd 每行都包含7个字段,之间用冒号分割,如下所示: mtk:x:1000:100:Michael:/home/mtk:/bin/base 按顺序介绍着7个字段: 登录名: 经过加密的密码:长度为13个字符 用户ID: 组ID: 注释:该字段存放关于用户的描述性文字. 主目录:用户登录后所处的初始路径 登录shell:一旦用于登录,便交由该程序控制 8.2 shadow密码文件: /etc/shadow 8.3 组文件:/etc/g

【Linux_Unix系统编程】Chapter10 时间

chapter10 时间 1:真实时间:度量这一时间的起点有二:(1)某个标准点:(2)进程生命周期内的某个固定时点(通常为程序启动) 2:进程时间:一个进程所使用的CPU时间总量,适用于对程序,算法性能的检查或优化.10.1 日历时间(calendar Time) 日历时间存储于类型为time_t的变量中. 系统调用gettimeofday(),可于tv指向的缓冲区中返回日历时间 #include <sys/time.h> int gettimeofday(struct timeval *t