文件I/O
来源:互联网 发布:比价软件淘宝小密 编辑:程序博客网 时间:2024/05/29 19:45
参考资料:W.Richard Stevens《UNIX环境高级编程》第4章、文件和目录
《从实践中学嵌入式linux应用程序开发》(华清远见嵌入式学院)第2章、嵌入式文件和I/O编程
资料下载:http://www.kuaipan.cn/file/id_43409466388906160.htm
-
文件描述符
对于linux而言,所有对设备和文件的操作都是使用文件描述符来进行的。文件描述符是一个非负的整数,它是一个索引值,并指向在内核中每个进程打开文件的记录表。当打开一个现存文件或者创建一个新文件时,内核就像进程返回一个文件描述符;当需要读写文件时,也需要把文件描述符作为参数传递给相应的函数。
通常,一个进程启动时,都会打开3个文件:标准输入、标准输出和标准错误处理。这3个文件分别对应文件描述符为0、1和2(也就是宏替换STDIN_FILENO,STDOUT_FILENO和STDERR_FILENO,鼓励用宏替换)
-
底层文件I/O操作
不带缓存的文件I/O 操作,主要用到5 个函数:open、read、write、lseek和close。这里的不带缓存是指每一个函数都只调用系统中的一个函数(不理解这句话的含义)。这些函数虽然不是ANSI C的组成部分,但是是POSIX 的组成部分。
使用实例:(从一个文件中读取最后10KB数据并复制到另一个文件中)
#include<unistd.h>#include<stdio.h>#include<stdlib.h>#include<fcntl.h>#include<sys/types.h>#include<sys/stat.h>#define BUFFER_SIZE 1024#define SRC_FILE_NAME "src_file"#define DEST_FILE_NAME "dest_file"#define OFFEST 10240int main(){ int src_file,dest_file; unsigned char buff[BUFFER_SIZE]; int real_read_len; src_file = open(SRC_FILE_NAME,O_RDONLY); dest_file = open(DEST_FILE_NAME,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if(src_file < 0 || dest_file < 0) { printf("open file error.\n"); exit(1); } //将源文件的读写指针移到最后10KB的起始位置 lseek(src_file,-OFFEST,SEEK_END); //读取源文件的最后10KB数据并写到目标文件中,每次读写1KB while((real_read_len = read(src_file,buff,sizeof(buff))) > 0) { write(dest_file,buff,real_read_len); } close(src_file); close(dest_file); return 0;}
-
文件锁
fcntl()函数
当多个用户共同使用、操作一个文件的时候,Linux通常采用的方法是给文件上锁,来避免共享的资源产生竞争的状态。
文件锁包括建议性锁和强制性锁。
在linux中,实现文件上锁的函数有lockf()和fcntl(),lockf()用于对文件施加建议性锁,而fcntl()不仅可以施加建议性锁,还可以施加强制性锁。同时,fcntl()还能对文件的每一记录上锁,也就是记录锁。
记录锁又可以分为读取锁和写入锁,其中读取锁又称为共享锁,写入锁又称为排斥锁。在文件的同一部分不能同时建立读取锁和写入锁。
fcntl()使用实例:
/*lock_set.c*/int lock_set(int fd,int type) { struct flock old_lock,lock; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; lock.l_type = type; lock.l_pid = -1; //判断文件是否可以上锁 fcntl(fd,F_GETLK,&lock); if(lock.l_type != F_UNLCK) { //判断文件不能上锁的原因 if(lock.l_type == F_RDLCK) { printf("read lock already set by %d\n",lock.l_pid); } else if(lock.l_type == F_WRLCK) { printf("write lock already set by %d\n",lock.l_pid); } //l_type可能已被F_GETLK修改过 lock.l_type = type; //根据不同的type值进行阻塞式上锁或解锁 if((fcntl(fd,F_SETLKW,&lock))<0) { printf("lock failed:type = %d\n",lock.l_type); return 1; } switch(lock.l_type) { case F_RDLCK: { printf("read lock set by %d\n",getpid()); } break; case F_WRLCK: { printf("write lock set by %d\n",getpid()); } break; case F_UNLCK: { printf("release lock by %d\n",getpid()); return 1; } break; default: break; } return 0;}
/*write_lock.c*/#include<unistd.h>#include<sys/types.h>#include<sys/stat.h>#include<stdio.h>#include<stdlib.h>#include<sys/file.h>#include "lock_set.c"int main(void){ int fd; fd = open("hello",O_RDWR|O_CREAT,0644); if(fd < 0) { printf("open file error\n"); exit(1); } //给文件上写入锁 lock_set(fd,F_WRLCK); getchar(); //给文件解锁 lock_set(fd,F_UNLCK); getchar(); close(fd); exit(0);}
用多个终端运行./write_lock可以得出:写入锁为互斥锁,同一时刻只能由一个写入锁存在。
/*read_lock.c*/#include<unistd.h>#include<sys/types.h>#include<sys/stat.h>#include<stdio.h>#include<stdlib.h>#include<sys/file.h>#include "lock_set.c"int main(void){ int fd; fd = open("hello",O_RDWR|O_CREAT,0644); if(fd < 0) { printf("open file error\n"); exit(1); } //给文件上写入锁 lock_set(fd,F_RDLCK); getchar(); //给文件解锁 lock_set(fd,F_UNLCK); getchar(); close(fd); exit(0);}
用多个终端运行./read_lock可以得出:读取锁为共享锁,同一时刻可以有多个读取锁存在。
-
I/O多路复用
在经典的《Unix网络编程第1卷》Chapter 6中作者详细介绍了五种I/O模型,分别为:
- blocking I/O
- nonblocking I/O
- I/O multiplexing (select and poll)
- signal driven I/O (SIGIO)
- asynchronous I/O (the POSIX aio_functions)
关于I/O模型可以参考http://www.cnblogs.com/leealways87/archive/2012/08/24/2654946.html
IO多路复用—select()可以参考http://www.cnblogs.com/ggjucheng/archive/2012/01/17/2324859.html
-
标准I/O编程
/*用标准IO库函数编写一个文件test.tx,每隔一秒向文件中写入一行数据,类似这样:1. 2007-7-30 15:16:422. 2007-7-30 15:16:43该程序应该无限循环,直到强制中断该进程为止(比如按Ctrl+C中断程序),下次再开启动程序写文件时应该将系统时间追加到源文件之后,并且序号能够接续上次的序号,比如:3. 2007-7-30 15:19:044. 2007-7-30 15:19:055. 2007-7-30 15:19:06*/
#include <time.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <strings.h>
int main(void){ FILE *fp_time, *fp_line; int n = 0; fp_time = fopen("test.txt", "a"); //setvbuf(fp_time, _IONBF, NULL, 0); if(access("line", F_OK)) // doesnot exist { fp_line = fopen("line", "w"); } else { fp_line = fopen("line", "r+"); fread(&n, sizeof(int), 1, fp_line); } char s[100]; time_t t; while(1) { time(&t); bzero(s, 100); snprintf(s, 100, "%d.\t", ++n); snprintf(s+strlen(s), 100-strlen(s), "%s", ctime(&t)); fputs(s, fp_time); fflush(fp_time); fseek(fp_line, 0, SEEK_SET); // rewind(fp_line); fwrite(&n, sizeof n, 1, fp_line); fflush(fp_line);
sleep(1);
}}
<script type="text/javascript"><!--google_ad_client = "ca-pub-1944176156128447";/* cnblogs 首页横幅 */google_ad_slot = "5419468456";google_ad_width = 728;google_ad_height = 90;//--></script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
- 文件I/O与标准I/O
- 标准I/O、文件I/O
- 文件I/O与标准I/O
- 异步文件 I/O
- 多媒体文件I/O
- 文件I/O
- 文件I/O操作
- 文件I/O操作
- 文件I/O操作
- 文件I/O
- I/O文件库
- 文件I/O
- 文件I/O
- 文件I/O
- 高级文件I/O
- unbuffered 文件I/O
- unix----文件I/O
- 文件I/O
- 嵌入式Linux设备驱动编程(1):基础
- 看 37signals 如何招聘 UI 设计师
- 嵌入式Linux网络编程
- 我的设计模式学习之路5(观察者模式)
- Linux任务、进程和线程
- 文件I/O
- 【转载】telnet: connect to address 127.0.0.1: Connection refused
- sqlyog企业版 v8.32注册码
- 系统配置
- Ubuntu gnome环境中给快捷菜单添加 Open in terminal 选项
- emacs执行qlsql时注意
- win7与VMware ubuntu虚拟机实现文件共享(最后一定要装open-vm-dkms插件)
- 为Ubuntu Gnome环境创建桌面快捷方式
- surfer 8 scripter 学习笔记(8)结合其它相关形成最终VB程序。