对于一块芯片,I/O和中断时必不可少的。
在OS中,I/O的概念很多,很杂;很难全部记清楚。
I/O是CPU与外设(包括内存、硬盘、键盘、鼠标、打印机等)之间通信的桥梁。
在linux中,一切都是文件,所以linux下I/O编程一般都是针对文件编程。
I/O大致可分为三类:
1.对系统指定的标准设备的输入和输出;即从键盘输入数据,输出到显示器屏幕;称为为标准I/O.
2.以外存磁盘文件为对象进行输入输出,称为文件I/O.文件IO是不带缓存的IO.
3.对内存中指定的空间进行输入输出;通常指定一个字符数组作为存储空间,称为字符串I/O.
I/O具体操作方式有:
1.底层I/O操作(open, read, lseek, write, close),底层I/O是不带缓存的I/O.
2.C流I/O
字符读写函数 :fgetc和fputc
字符串读写函数:fgets和fputs
格式化读写函数:fscanf和fprinf
二进制、数据块读写函数:freed和fwrite
3.面向对象C++流I/O
iostream:定义读写控制窗口的类型
fstream:定义读写已命名文件的类型。
sstream:读写内存中string对象
文本文件读写:<<,>> (>>会跳过空白,不能读入带空格的字符串)
字符逐行读写: getline
单个字符数据的输入读写:put, get
二进制、读写数据块:read, write
下面这段测试代码用于测试3种IO操作读写二进制文件效率。
结论是:文件I/O最慢,C流I/O和面向对象C++流I/O 差不多(C++流稍快)。
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int test_io_efficiency()
{
char buffer[1024];
timeval tv;
timeval tv2, tv3, tv4, tv5, tv6;
long long L1, L2, L3, L4, L5, L6;
int i;
/*****************文件I/O测试********************/
int fileA, fileB;
if(( fileA= open("source.rar", O_RDONLY))<0) //open() 是系统调用 返回的是文件句柄,文件的句柄是文件在文件描述副表里的索引,fopen()是C的库函数,返回的是一个指向文件结构的指针。
return 0;
if((fileB= open("destinationA.rar", O_RDWR|O_CREAT|O_TRUNC))<0) //如果文件存在,会直接退出
return 0;
int fileA2 = dup(fileA); //test, 复制一个文件描述符2
if(fileA2 == -1)
{
printf("dup failed \n");
return 0;
}
int fileA3;
if((fileA3 =fcntl(fileA2, F_DUPFD, 0))<0)//test, 复制一个文件描述符3
{
printf("fcntl dup failed \n");
return 0;
}
int len= lseek(fileA3,0,SEEK_END); //文件的长度,从0开始
printf("lseek end len %d\n",len);
len =lseek(fileA3,0,SEEK_SET); // 从826132252开始读起
printf("lseek set len %d\n",len);
gettimeofday(&tv, NULL);
L1 = tv.tv_sec*1000*1000+tv.tv_usec;
//while((i= read(fileA,buffer, 1024))>0)
while((i= read(fileA3,buffer, 512))>0) //为了效果明显,3种IO操作buffer大小都为512
{
write(fileB, buffer, i);
}
close(fileA);
close(fileB);
gettimeofday(&tv2, NULL);
L2 = tv2.tv_sec*1000*1000+tv2.tv_usec;
printf("%lld\n",L2-L1); //打印出I/O读写总时间
/*****************C 标准I/O测试********************/
gettimeofday(&tv3, NULL);
L3 = tv3.tv_sec*1000*1000+tv3.tv_usec;
FILE *fileC, *fileD;
if((fileC = fopen("source.rar","rb")) == NULL)
return 0;
if((fileD = fopen("destinationB.rar","wb+")) == NULL)
return 0;
//fread(读入数据的存放地址, size要读写的字节数, 要进行读写多少个size字节的数据项, 文件指针)
while((i= fread(buffer,1,512,fileC))>0)
{
fwrite(buffer,1,i,fileD);
}
fclose(fileC);
fclose(fileD);
gettimeofday(&tv4, NULL);
L4 = tv4.tv_sec*1000*1000+tv4.tv_usec;
printf("%lld\n",L4-L3);
/*****************C++ 面向对象I/O测试********************/
gettimeofday(&tv5, NULL);
L5 = tv5.tv_sec*1000*1000+tv5.tv_usec;
ifstream inPut;
inPut.open("./source.rar", ios::binary);
if (!inPut.good())
{
inPut.close();
return 0;
}
ofstream outPut;
outPut.open("./destinationC.rar", ios::binary);
if(!outPut)
{
outPut.close();
return 0;
}
while(!(inPut.eof()))
{
//inPut.getline(buffer, 1024);
inPut.read(buffer, 512);
//if (strlen(buffer) == 0)
// continue;
outPut.write(buffer, 512);
//outPut.flush(); //如果每次都flush,效率会很低
}
inPut.close();
outPut.close();
gettimeofday(&tv6, NULL);
L6 = tv6.tv_sec*1000*1000+tv6.tv_usec;
printf("%lld\n",L6-L5);
return 1;
}
int main()
{
test_io_efficiency();
return 1;
}