`

UNIX环境高级编程 文件I/O

 
阅读更多

 

 

 

#include <fcntl.h>
int open(const char *path, int oflag, /* mode_t mode */ );
int openat(int fd, const char *path, int oflag, /* mode_t mode */ );
//返回文件描述符

STDIN_FILENO      //标准输入
STDOUT_FILENO   //标准输出

#include<fcntl.h>
int creat(const char *path, mode_t moe);
//返回文件描述符,负数表示错误

#include <unistd.h>
int close(int fd);
//关闭一个文件还会释放该进程在该文件上的所有锁记录

#include <unistd.h>
off_t  lseek(int fd, off_t offset, int whence);
//1.若whence是 SEEK_SET,则将该文件的偏移量设置为距离文件开始出offset个
   //字节
//2.若whence是 SEEK_CUR,则将该文件的偏移量设置为其当前值加offset,
  //offset可为正或负
//3.若whence是 SEEK_END,则将该文件的偏移量设置为文件长度加offset,
  //offset可正可负


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

//read成功,返回读到的字节数,如果已达到文件尾端则返回0
//读普通文件时,读要求的字节数之前已经达到文件尾端则返回0
/从终端设备读一次最多读一行
//从网络读,网络中的缓冲机制可能造成返回值小于所要求读的字节数
//当从管道或FIFO读时,若管道包含的字节少于所需的数量,那么read将返回实际
   //可用的字节数
//当从某些面向记录的设备(如磁带)读时,一次最多返回一个记录
//当一信号造成中断,而已经读了部分数据时,在成功返回之前,该偏移量将增加
   //实际读到的字节数
//write成功,返回实际写入的字节数


//原子性的执行读写操作
#include <unistd.h>
ssize_t pread(int fd, void *buf, size_t nbytes, off_t offset);
ssize_t pwrite(int fd, void *buf, size_t nbytes, off_t offset);


//复制文件描述符
#include <unistd.h>
int dup(int fd);
int dup2(int fd, int fd2);


//同步刷新
#include <unistd.h>
int fsync(int fd);
int fdatasync(int fd);
void sync(void);
//sync只是将所有修改过的块缓冲区排入写队列,然后就返回,并不等待实际写
//磁盘操作结束
//一般系统守护进程30秒调用sync函数
//fsync函数只对文件描述符fd指定的一个文件起作用,并且等待写磁盘操作结束
//fdatasync函数类似fsync,但是只影响文件的数据部分,fsync还会同步更新
  //文件的属性



//更改已经打开文件的属性
#include <fcntl.h>
int fcntl(int fd, int cmd, /* int arg */);
//fcntl函数有5种功能
//1.复制一个已经的描述符(cmd=F_DUPFD或F_DUPFD_CLOEXEC)
//2.获取/设置文件描述符标志(cmd=F_GETFD或F_SETFD)
//3.获取/设置文件状态标志(cmd=F_GETFL或F_SETFL)
//4.获取/设置异步I/O所有权(cmd=F_GETOWN或F_SETOWN)
//5.获取/设置记录锁(cmd=F_GETLK,F_SETLK或F_SETLKW)


//杂物箱函数
#include <unistd.h>
#include <sys/ioctl.h>   //BSD and linux
int ioctl(int fd, int request);



 

 

open函数的oflag参数

参数 含义
O_RDONLY 只读打开
O_WRONLY 只写打开
O_RDWR 读,写打开
O_EXEC 只执行打开
O_SEARCH 只搜索打开
O_APPEND 每次写时都追加到文件尾端
O_CLOEXEC

把FD_CLOEXEC常量设置为文件描述符

O_CREAT

若文件不存在则创建它,同时需要第三个参数指明

新文件的访问权限

O_DIRECTORY 如果path不是目录则出错
O_EXCL

如果同时指定了O_CREAT,而文件已存在则出错

次功能可测试一个文件是否存在若不存在则创建

O_NOCTTY

如果path引用的是终端设备,则不将该设备分配作为

进程的控制终端

O_NOFOLLOW

如果path引用的是一个符号链接则出错

O_NONBLOCK

如果path引用的是一个FIFO,一个块特文件或一个字符特殊文件,则

此选项为文件的本次打开操作和后续的I/O操作设置为非阻塞方式

O_SYNC

每次write等待物理I/O操作完成,包括由该write操作引起的文件属性更新

所需的I/O

O_TRUNC

如果此文件存在,而且为只写或读-写成功打开,则将其长度截断为0

O_TTY_INIT

如果打开一个还未打开的终端设备,设置非标准termios参数值,使其符合Single

UNIX Specificationi

O_DSYNC

每次write要等待物理I/O操作完成,但如果该写操作并不影响读取写入的数据,

则不需要等待文件属性被更新

O_RSYNC

使每一个以文件描述符作为参数进行的read操作等待,直至所有对文件同一部分挂起

的写操作都完成

 

 

 

写空洞的例子

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

char buf1[] = "abcdefghij";
char buf2[] = "ABCDEFGHIJ";

int main(int argc, char *argv[]) {

        if(argc < 2) {
                printf("input create file path!\r\n");
                return 1;
        }

        int fd;
        if( (fd=creat(argv[1],0755)) < 0 ) {
                printf("create error");
                printf("\r\n");
        }

        if( write(fd,buf1,10) != 10 ) {
                printf("buf write error");
                printf("\r\n");
        }

        if( lseek(fd,16384, SEEK_SET) == -1) {
                printf("lseek error");
                printf("\r\n");
        }

        if( write(fd,buf2,10) != 10 ) {
                printf("buf2 write error");
                printf("\r\n");
        }
        return 0;
}

 

 

读写文件的例子,将一个文件读取,写入到另一个文件中

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#define BUFFSIZE 4096
int main(int argc, char *argv[]) {
        if(argc < 3) {
                printf("input read path, write path\r\n");
                return 1;
        }
        int r_fd;
        if( (r_fd=open(argv[1],O_RDONLY)) < 0 ) {
                printf("open error\r\n");
        }
        int w_fd;
        if( (w_fd=creat(argv[2],0755)) < 0 ) {
                printf("create error\r\n");
        }

        int num;
        char buf[BUFFSIZE];
        while( (num=read(r_fd, buf, BUFFSIZE)) > 0) {
                if( write(w_fd, buf, num) != num ) {
                        printf("write error\r\n");
                }
        }
        if( num < 0 ) {
                printf("read error\r\n");
        }
        return 0;
}

 

读写文件时候,buf大小不同对影响的影响,12核/12G内存

buf大小 真正时间 用户时间 系统时间
512 3.269s 0.077s 2.523s
1024 1.793s 0.039s 1.723s
2048 1.682s 0.015s 1.214s
4096 2.410s 0.017s 2.184s
8192 5.404s 0.009s 1.218s
16384 5.433s 0.013s 1.175s
32768 5.396s 0.005s 1.188s
65535 5.383s 0.004s 1.205s
8M 0.878s 0.000s 0.876s

 

如果没每一次,调用fsync(fd)将内存刷新到磁盘上,性能结果如下:

buf大小 真实时间 用户时间 系统时间
1024 1m52.317s 0.386s 12.616s
2048 1m7.329s 0.086s 8.528s
4096 36.584s 0.036s 4.183s
8192 20.883s 0.085s 2.886s
16384 13.335s 0.026s 2.200s
32768 9.761s 0.020s 1.711s
65535 6.901s 0.010s 1.462s
8M 5.675s 0.001s 1.199s

 

 

 

 

UNIX支持在不同进程共享打开文件,内核使用三种数据结构表示打开文件

1.每个进程再进程表中都有一个记录项,记录项中包含一张打开文件描述符表,可将其视为一个矢量,每个

   描述符 占用一项,与每个文件描述符相关联的是:

   a)文件描述符标志(close_on_exec)

   b)指向一个文件表项的指针

2.内核为所有打开文件维持一张文件表,每个文件表项包含:

   a)文件状态标志(读,写,添写,同步和非阻塞等)

   b)当前文件偏移量

   c)指向该文件v节点表项的指针

3.每个打开文件(或设备)都有一个v节点,linux没有v节点而是用通用的 i节点结构。v节点包含了文件类型和对

  此文件进行各种操作的函数指针,对于大多数文件,v节点还包含了该文件的 i节点(i-node)。这些信息是在

  打开文件时从磁盘上读入内存的,所以文件的所有相关信息都是随时可用的。

 

打开文件的内核数据结构


 

两个独立进程各自打开同一个文件


 

 

原子操作

早起的unix版本不支持O_APPEND选项,所以程序被编写成下列形式

 

if( lseek(fd,0L2) < 0 ) {
    err_sys("lseek error");
}
if( write(fd, buf, 100) != 100 ) {
    err_sys("write error");
}

 

 

创建一个文件

 

if( (fd=open(path,O_WRONLY)) < 0 ) {
    if(errno == ENOENT) {
        if( (fd=creat(path,mode)) < 0 ) {
            err_sys("create error");
        }
    } else {
        err_sys("open error");
    }
}
 

 

fcntl函数的cm参数有11个,先说明前8个,后3个跟锁有关

参数 含义
F_DUPFD 复制文件描述符fd
F_DUPFD_CLOEXEC

复制文件描述符,设置与新描述符关联的FD_CLOEXEC文件描述符

标志的值,返回新文件描述符

F_GETFD

对应于fd的文件描述符标志作为函数值的返回。当前只定义了一个文件

描述符标志FD_CLOEXEC

F_SETFD 对于fd设置文件描述符标志
F_GETFD 对于fd设置文件描述符标志
F_GETFL 对应于fd的文件状态标志作为函数值返回
F_SETFL

将文件状态标志设置为第三个参数的值,可以更改的几个标志是

O_APPEND,O_NONBLOCK,O_SYNC,O_DSYNC,O_RSYNC,

O_FSYNC和O_ASYNC

F_GETOWN

获取当前接收SIGIO和SIGURG信号的进程ID或进程组ID

F_SETOWN

设置接收SIGIO和SIGURG信息的进程ID或进程组ID

 

对于F_GETFL的函数返回值,在open函数中有说明,返回下列内容

文件状态标志 说明
O_RDONLY 只读打开
O_WRONLY 只写打开
O_RDWR 读写打开
O_EXEC 只执行打开
O_SEARCH 只搜索目录打开
O_APPEND 追加写
O_NONBLOCK 非阻塞模式
O_SYNC 等待写完成(数据和属性)
O_DSYNC 等待写完成(仅数据)
O_RSYNC 同步读和写
O_FSYNC 等待写完成(仅BSD和Mac)
O_ASYNC 异步I/O(仅BSD和Mac)

 

 

 

 

/dev/fd

较新的系统都提供名为 /dev/fd 的目录,其目录项是名为 0,1,2,等的文件,打开文件/dev/fd/n 等效于复制

描述符n

cat命令对其采用了一种特殊处理

 

filter file2 | cat file1 - file3 | ipr
//首先cat读file1,然后是标准输入,然后是file3
//如果cat支持/dev/fd 也可以改成
filter file2 | cat file1 /dev/fd/0 file3 | ipr

 

 

 

 

 

 

  • 大小: 27.7 KB
  • 大小: 39.5 KB
分享到:
评论

相关推荐

    UNIX环境高级编程_Linux/Unix编程_

    《UNIX环境高级编程》是一本深入探讨Linux/Unix系统编程的经典著作,对于任何希望在这些操作系统上进行系统级编程的开发者来说,都是不可或缺的参考书。这本书详细介绍了如何利用UNIX/Linux系统的API和工具来构建...

    UNIX环境高级编程-pdf

    《UNIX环境高级编程》是一本深受程序员和...通过结合这两个文件,你可以获得更全面的学习资料,加深对UNIX环境高级编程的理解。无论是自学还是作为参考手册,这本书及其相关资料都能为你的UNIX编程之路提供强大的支持。

    UNIX环境高级编程

    《UNIX环境高级编程》是一本深入探讨UNIX系统编程的权威参考书籍。它涵盖了UNIX编程的各个方面,从基础的UNIX系统结构和原理,到文件操作、进程控制、进程间通信、多线程编程、网络编程以及终端I/O和伪终端等内容。...

    APUE(UNIX环境高级编程)——文件I/O篇

    在UNIX环境中,文件I/O是程序与存储设备交互的基本方式,主要涉及五个核心函数:`open`、`read`、`write`、`lseek`和`close`。这些函数构成了不带缓存的I/O(unbuffered I/O),即每次读写操作都会直接调用内核的...

    Unix I/O 小结

    Unix I/O系统是操作系统的核心部分,它提供了对文件和设备进行输入输出操作的接口。本文主要总结了Unix下的I/O模型及其相关系统调用。 在Unix中,每个进程都有一个打开文件描述符表,用于存储指向文件inode的指针和...

    UNIX环境高级编程.pdf

    ### UNIX环境高级编程知识点概述 #### 一、UNIX基础知识 **1.1 引言** 在计算机科学领域,操作系统作为连接硬件与软件的桥梁,为应用程序提供了必要的服务,包括但不限于执行新程序、打开文件、读取文件内容、...

    UNIX环境高级编程(中文版)

    《UNIX环境高级编程》是一本深受程序员和系统管理员喜爱的经典之作,它由W. Richard Stevens撰写,对中国乃至全球的UNIX和Linux开发者具有深远影响。这本书深入浅出地讲解了在UNIX系统上进行程序开发的各种技术和...

    UNIX环境高级编程(中文第三版)高清完整

    书中除了介绍UNIX文件和目录、标准I/O库、系统数据文件和信息、进程环境、进程控制、进程关系、信号、线程、线程控制、守护进程、各种I/O、进程间通信、网络IPC、伪终端等方面的内容,还在此基础上介绍了众多应用...

    Unix环境高级编程_UNIX环境高级编程_

    《Unix环境高级编程》是一本深入探讨Unix操作系统编程的经典之作,由W. Richard Stevens撰写,是许多计算机科学专业学生和专业开发者的必备参考书。这本书详细介绍了如何在Unix系统上进行系统级编程,包括文件I/O、...

    UNIX环境高级编程(PDF超清版)

    关于文件名称列表中的"UNIX环境高级编程",这可能表示所有章节的PDF文件都集中在一个同名的压缩包内。通常,这样的压缩文件会包含一系列按照章节命名的PDF,例如"第1章_进程管理.pdf"、"第2章_文件系统接口.pdf"等,...

    Unix环境高级编程中英文版包括源代码

    《Unix环境高级编程》是一本深受程序员和系统管理员喜爱的经典之作,主要涵盖了在Unix操作系统环境下进行高级编程的各种技术和方法。这本书分为多个章节,详细讲解了Unix系统接口、进程管理、文件系统、网络通信等...

    UNIX环境高级编程课后习题详细解答

    "UNIX环境高级编程"通常涵盖的主题包括进程管理、文件I/O、信号处理、网络编程、系统调用接口以及内存管理等。 课后习题往往旨在巩固和深化对这些概念的理解。以下是一些可能涉及的知识点: 1. **进程管理**:包括...

    unix环境高级编程第三版 英文版

    这本书涵盖了Unix系统的方方面面,包括进程管理、文件I/O、网络编程、信号处理、内存映射、多线程、进程间通信等核心主题。以下是一些主要知识点的详细介绍: 1. **进程管理**:Unix系统中的进程是程序执行的实例。...

    unix环境高级编程.rar

    unix环境高级编程 pdf高清无水印 第1章 UNIX基础知识 1 第2章 UNIX标准化及实现 17 第3章 文件I/O 35 第4章 文件和目录 54 第5章 标准I/O库 91 第6章 系统数据文件和信息 110 第7章 UNIX进程的环境 122 第8章 进程...

    UNIX环境高级编程第二版

    《UNIX环境高级编程第二版》是一本全面而深入的UNIX系统编程指南,它不仅教授了C语言在UNIX环境下的具体应用,还涵盖了文件I/O、进程控制、信号处理、网络编程等关键主题。通过阅读本书,读者将能够掌握UNIX系统编程...

    UNIX环境高级编程(清晰PDF中文第一版)

    《UNIX环境高级编程》是一本深受IT专业人士喜爱的经典著作,尤其对于那些致力于深入理解Linux操作系统以及UNIX系统的开发者和系统管理员而言,这本书具有极高的参考价值。作为“学习Linux最好的两本书之一”,它与...

Global site tag (gtag.js) - Google Analytics