热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

《APUE》Chapter3FileI/O(学习笔记加上自己的代码)

FileIO文件IO在Unix系统中,文件IO大多数的使用五大函数来实现:open,read,write,lseek和cl

File I/O



文件I/O

在Unix系统中,文件I/O大多数的使用五大函数来实现:open,read,write,lseek 和close.

术语unbuffered的意思是每个read或者write函数向内核请求一个系统调用


对于内核而言,每一个打开的文件都有相应的file descriptors(非负整数).


open 函数

#include

int open(const char* pathname,int oflag,......,/*  mode_t mode  */);

如果正确返回file descriptor,否则返回 -1

pathname是文件名的路径,oflag是option flag,选项标签这里的选项是宏定义

oflag宏:

O_RDONLY    只可读

O_WRONLY  只可写

O_RDWR        可读写

O_APPEND    对于每个write函数的写入点从当前文件末尾开始

O_CREAT      如果文件不存在,就创建这个文件。

当然这个对于open函数使用的选项需要和函数的第三个参数mode一起,mode用于描述新建文件的权限

O_EXCL      如果使用了O_CREAT宏,并且这个文件已经存在了,于是 产生一个错误

O_TURNC   如果文件存在了并且被每一个write或者read函数成功的打开了,这个选项将“命令“open函数去清空所有文件内容,使之文本长度为0.

O_NOCTTY  如果pathname提及的是terminal设备,不允许设备被作为controling terminal 

O_DSYNC   使得write等待每一个物理I/O完成自己的工作,但是不等待那种不影响读取刚写入的数据的文件

O_RSYNC     在任何write操作对于某一文件的同一部分写入操作完成之前,让被read操作的file descriptor所指的文件保持等待

/***************
just a demo
***************/
#include"apue.h"
#include"fcntl.h"
#include"stdio.h"int main()
{int file_descriptor &#61; 0;if(file_descriptor &#61; open("./text.t",O_RDONLY) <0){printf("open error\nprocess end\n");return 0;}else{printf("open success\n");close(file_descriptor);//if there is not close function ,it would be OK...}return 0;
}




creat 函数

#include

int creat(const char* pathname,mode_t mode);

如果函数成功就返回打开的文件的file descriptor&#xff0c;否则返回-1

mode &#xff1a;

 S_IRUSR   用户可读

 S_IWUSR   用户可写

 S_IXUSR   用户可执行

#include
#include
#include#define RWX (S_IRUSR | S_IWUSR | S_IXUSR)int main()
{int file_descriptor &#61; 0;if((file_descriptor &#61; creat("./hello.t",RWX)) <0){printf("creat fail\nprocess end");return 0;}else{printf("creat successful\n");}close(file_descriptor);return 0;
}







close函数

#include

int  close(int filedes)

如果成功返回0&#xff0c;否则返回-1


每个文件都有一个相关的“当前文件偏置”(current file offset)&#xff0c;通常是一个非负整数。它测量表示的意义是从文件开头到结束的地方这段区域内&#xff0c;所含字节数。

read函数write函数的读写操作通常从这个offset开始

通常(default情况)&#xff0c;offset被初始化为0.


lseek函数

#include"unistd.h"//unistd.h - standard symbolic constants and types

off_t lseek(int files,  off_t offset,   int whence)

如果成功返回file offset&#xff0c;否则返回-1

whence宏&#xff1a;

SEEK_SET 将文件的offset设置为文件开头

SEEK_CUR将文件的offset设置为当前值加上lseek的第二参数offset的值(offset必须为正数)

SEEK_END将文件的offset设置为文件的大小加上lseek的第二个参数offset的值(offset可正可负)

/*
just a demo for lseek
*/
#include"apue.h"
#include"stdio.h"
#include"unistd.h"
#include"fcntl.h"int main()
{off_t file_off_set &#61; 0;int file_descriptor &#61; 0;if((file_descriptor &#61; open("./text.t",O_RDONLY)) <0){printf("open error\nProcess end\n");return 0;}if((file_off_set &#61; lseek(file_descriptor,file_off_set,SEEK_CUR)) <0){printf("lseek error\n");return 0;}else{printf("lseek execute successful\nCurent file off-set is %d\n",file_off_set);}return 0;
}







atomic operation微操作

#inlcude
ssize_t pread(int filedes, void * buf,size_t nbytes,off_t offset);

ssize_t pwrite(int filedes,const void*buf,size_t nbytes,off_t offset);

调用pread函数就相当于调用lseek函数之后紧接着调用read函数。这两者几乎是等价的&#xff0c;除了下面两点情况

1.调用pread的时候&#xff0c; 没有什么办法可以打断这两者(lseek和read)操作

2.文件指针没有更新

pwrite同理


          简单的说&#xff0c;atomic operation就是指的一种操作。这种操作可能由其他多种操作组成(multiple step)。

这个atomic operation有个特点&#xff0c;就是这个atomic operation包含的操作步骤(step)要么都完成&#xff0c;要么都不

会开始进行。这个atomic operation中不会有其他的操作“夹杂着"发生。

下面是man pwrite 的结果&#xff1a;

pwrite()  writes  up  to  count  bytes from the buffer

starting at buf to the file descriptor  fd  at  offset     

The file offset is not changed.


         值得注意的是这里的offset 是个定值而不是动态获得的&#xff0c;也就是说可能覆盖之前的文本内容(亲测&#xff0c;有这个情况)

如果要动态更新offset达到&#xff0c;每次都在 “新的文本末尾" 写入数据的话&#xff0c;那么则需要lseek和SEEK_END来实现更新offset

动态更新的在文本末尾写入数据用pwrite是没有必要的&#xff0c;lseek&#43;write就可以了

my source code&#xff1a;

#include"unistd.h"
int dup(int fd);
int dup2(int fd,int fd2)
对于file descriptor的复制



              These  system calls create a copy of the file descriptor oldfd. dup() uses the lowest-numbered unused descriptor  for the new descriptor.  dup2() makes newfd be the copy of oldfd, closing newfd  first if necessary, but note the following: 
        *  If oldfd is not a valid file descriptor,  then  the call fails, and newfd is not closed.    
        *  If  oldfd is a valid file descriptor, and newfd has the same value as oldfd, then dup2() does  nothing,  and returns newfd.


#include"apue.h"
#include"unistd.h"
#include"fcntl.h"
int main()
{int file_descriptor &#61; 0;int duped_fd &#61; 0;if((file_descriptor &#61; open("./text.t",O_RDONLY)) <0){printf("open error\nprocess end\n");return 0;}else{duped_fd &#61; dup(file_descriptor);printf("The duped file descriptor is %d\n",duped_fd);printf("The file_descritor before dup:%d\n",file_descriptor);}return 0;
}


NAME

       fsync,  fdatasync - synchronize a file&#39;s in-core state  with storage device



#include int fsync(int fd);#include
int fcntl(int filedes, int cmd,.../*int arg*/);


filedes文件标志符
cmd是参数宏&#xff0c;总共有十个&#xff0c;第三章只讨论前面七个&#xff0c;后面三个再第14章讨论
在秒速记录锁&#xff08;record locking&#xff09;的时候&#xff0c;第三个参数是一个指向结构体的指针
fcntl被用作五种不同的路径
第一&#xff0c;复制已经存在的文件标志符&#xff08;descriptor&#xff09;cmd  &#61; F_DUP
第二&#xff0c;设置或者获得文件标识符cmd &#61; F_GETFD或者 cmd &#61; F_SETFD
第三&#xff0c;设置或者获得状态符&#xff08;status flag&#xff09; cmd &#61; F_GETFL或则F_SETFL
status flag: 

     O_RDWR

     O_RDONLY
     O_WRONLY
     O_APPEND
     O_NONBLOCK
     O_SYNC
     O_DSYNC
     O_RSYNC
     O_FSYNC

     O_ASYNC

第四&#xff0c;设置或则获得异步I/O权限(asynchronous I/O ownership)cmd &#61; F_GETOWN or cmd &#61; F_SETOWN
第五&#xff0c;设置或者获得记录锁(record lock)(cmd &#61; F_GETLK, or cmd &#61; F_SETLK)


#include
#include
#include
int main()
{int file_descriptor &#61; 0;int copy_file_descriptor &#61; 0;int file_flags &#61; 0;int ownership &#61; 0;int temp &#61; 0;if((file_descriptor &#61; open("./text.t",O_RDWR)) <0){printf("open error\nProcess end\n");return 0;}printf("file_descriptor is %d\n",file_descriptor);//cmd &#61; F_DUPFD ,dupliacte the file descriptorif((copy_file_descriptor &#61; fcntl(file_descriptor,F_DUPFD,0)) <0){printf("fcntl error\nProcess end");return 0;}else{printf("The return value is %d\n",copy_file_descriptor);}//cmd &#61; F_GETFD, return file descriptor flass for fiedes as the vale of the fucntionif(temp &#61; fcntl(file_descriptor,F_GETFD) <0){printf("fcntl error\nProcess end\n");return 0;}else{printf("file descriptor is %d\n",temp);}//cmd &#61; F_GETFL,return file status flags for filedes.if(file_flags &#61; fcntl(file_descriptor,F_GETFL) <0){printf("fcntl error\nProcess end\n");return 0;}else{switch(file_flags& O_ACCMODE) //& O_ACCMODE){case O_RDWR :printf("file flags is O_RDWR\n");break;case O_RDONLY:printf("file flags is O_RDONLY\n");break;case O_WRONLY:printf("file flags is O_WRONLY\n");break;}if(file_flags&O_APPEND){printf("file flags is O_APPEND\n");} if(file_flags&O_NONBLOCK){printf("file flags is O_NONBLOCK\n");}#if defined(O_SYNC)if(file_flags&O_SYNC){ printf("file flags is O_SYNC\n");}#endif#if defined(O_DSYNC)if(file_flags&O_DSYNC){printf("file flags is O_DSYNC\n");}#endif#if defined(O_FSYNC)if(file_descriptor&O_FSYNC) {printf("file flags is O_FSYNC\n");}#endif#if defined(O_ASYNC)if(file_descriptor& O_ASYNC){printf("file flags is O_ASYNC\n");} #endif#if defined (O_RSYNC)if(file_descriptor&O_RSYNC){printf("file flags is O_RSYNC\n");}#endif}//cmd &#61; F_GETOWNif(ownership &#61; fcntl(file_descriptor,F_GETOWN) <0){printf("fcntl error!\nProcess end\n");return 0;}else{printf("file ownership is %d",ownership);}return 0;
}



在 /dev/fd文件夹目录下的文件&#xff0c;如果被打开&#xff0c;相当于复制该文件标志符。














推荐阅读
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文讨论了在Spring 3.1中,数据源未能自动连接到@Configuration类的错误原因,并提供了解决方法。作者发现了错误的原因,并在代码中手动定义了PersistenceAnnotationBeanPostProcessor。作者删除了该定义后,问题得到解决。此外,作者还指出了默认的PersistenceAnnotationBeanPostProcessor的注册方式,并提供了自定义该bean定义的方法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
author-avatar
黑鸽子
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有