Linux文件操作(文件I/O--文件阻塞)

非阻塞文件I/O

非阻塞文件I/O的概念

操作系统通过I/O与外部设备进行交互。这些外部设备可能是本地磁盘,也可能是网络文件系统。外部设备的I/O速度是不同的,有的很快(例如本地的磁盘读写),有的却很慢(例如网络间的数据传输)。速度较慢的I/O会造成读写函数阻塞。例如,一个应用程序调用read函数从远程的文件系统中读取数据,这时需要传输的数据由于网络连接的问题致使传输速度很慢;或者在传输过程中由于某些意外,需要的数据丢了.此时应用程序调用的read函数就会因为读取不到数据而阻塞,直到需要的数据可以读写为止。为了防止I/O操作不必要的阻塞造成应用程序不能正常执行, Linux系统允许用户以非阻塞的方式打开一个文件。 当使用该种方式打开文件后,如果遇到需要读写的外部设备的数据不可用,I/O 操作函数不会阻塞而是返回,并将ermo变量设置为EAGAIN。该错误号表示IO系统调用没有阻塞等待数据,导致本次读写操作失败。

以非阻塞方式打开文件

Linux环境下可以在调用open函数打开-一个文件的同时使用O_ NONBLOCK选项将打开的文件设置为非阻塞方式。

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

#define MAX 100000
#define LEN 1024  /* 使用宏最为缓冲区的大小 */

int main(int argc, char *argv[ ])
{
	int fd1, fd2; 
	FILE *fp;
	char buf[MAX]; /* 大文件的缓冲区 */
	int n, rest;
	char *p = buf;
	char content[LEN];

	if(argc != 3){ /* 缺少文件名 */
		printf("expect args\n");
		exit(1);
	}

	fd1 = open(argv[1], O_RDONLY); /* 输入文件 */
	if(fd1 == -1){
		perror("fail to read");
		exit(1);
	}

	fp = fopen(argv[2], "w"); /* 输出错误原因的文件,使用格式化I/O */
	if(fp == NULL){
		perror("fail to read");
		exit(1);
	}

	fd2 = open("test.txt", O_WRONLY|O_NONBLOCK); /* 输出文件,低速文件test.txt文件 */
	if(fd2 == -1){
		perror("fail to read");
		exit(1);
	}

	rest = read(fd1, buf, MAX); /* 读文件的内容到缓冲区 */
	printf("get %d bytes from %s\n", rest, argv[1]);

	while(rest > 0){ /* 当要输出的内容还有剩余时继续输出 */
		errno = 0;
		n = write(fd2, p, rest); /* 输出缓冲区内容 */
		
		fprintf(fp, "write %d, errno %s\n", n, strerror(errno)); /* 如果输出失败则输出错误原因 */
		if(rest > 0){ /* 计算剩余的字节数 */
			p += n;
			rest -= n;
		}
	}

	printf("done\n");

	return 0;
}

将一个打开文件设置为非阻塞方式

对于一个已经打开的文件,Linux 系统同样可以将其设置为非阻塞方式。非阻塞被实现为文件描述符中的一一个文件状态标志。由于需要修改一个已经打开文件的状态标志,这时需要使用fcntl 函数对此进行操作。

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

#define MAX 100000
#define LEN 1024

int main(int argc, char *argv[ ])
{
	int fd1, fd2; 
	FILE *fp;
	char buf[MAX]; /* 大文件的缓冲区 */
	int n, rest;
	char *p = buf;
	char content[LEN];
	int flags;

	if(argc != 3){ /* 缺少文件名 */
		printf("expect args\n");
		exit(1);
	}

	fd1 = open(argv[1], O_RDONLY); /* 打开输入文件 */
	if(fd1 == -1){
		perror("fail to read");
		exit(1);
	}

	fd2 = open(argv[2], O_WRONLY); /* 打开输出出错信息的文件 */
	if(fd2 == -1){
		perror("fail to read");
		exit(1);
	}

	fp = fdopen(fd2, "w"); /* 打开文件,以只写的方式 */
	if(fp == NULL){
		perror("fail to open");
		exit(1);
	}

	flags = fcntl(STDOUT_FILENO, F_GETFL, 0); /* 将标准输出设置为非阻塞形式 */
	if(flags == -1){
		perror("fail to fcntl");
		exit(1);
	}
	flags |= O_NONBLOCK; /* 设置非阻塞标志 */
	if(fcntl(STDOUT_FILENO, F_SETFL, flags) == -1){ /* 重新设置文件的状态标志 */
		perror("fail to fcntl");
		exit(1);
	}

	rest = read(fd1, buf, MAX); /* 读入文件 */
	printf("get %d bytes from %s\n", rest, argv[1]);

	while(rest > 0){ /* 当要输出的内容还有剩余时继续输出 */
		errno = 0;
		n = write(STDOUT_FILENO, p, rest); /* 输出缓冲区内容 */
		
		fprintf(fp, "write %d, errno %s\n", n, strerror(errno)); /* 如果输出失败则输出错误原因 */
		if(rest > 0){ /* 计算剩余的字节数 */
			p += n;
			rest -= n;
		}
	}

	printf("done\n");

	close(fd1); /* 关闭文件 */

	fclose(fp);

	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值