Linux编程——文件 IO操作
2015-08-21 08:15
603 查看
Linux文件I\O介绍
1.Linux系统调用Linux系统调用(systemcall)是指操作系统提供给用户程序的一组“特殊接口”,用户程序可以通过这组“特殊”接口来获得操作系统提供的特殊服务。为了更好的保护内核空间,将程序的运行空间分为内核空间和用户空间,他们运行在不同的级别上,在逻辑上是相互隔离的。在Linux中,用户程序不能直接访问内核提供的服务,必须通过系统调用来使用内核提供的服务。Linux中的用户编程接口(API)遵循了UNIX中最流行的应用编程界面标准——POSIX。这些系统调用编程接口主要是通过C库(libc)实现的。2.文件描述符对内核而言,所有打开文件都由文件描述符引用。文件描述符是一个非负整数。当打开一个现存文件或创建一个新文件时,内核向进程返回一个文件描述符。当写一个文件时,用open或create返回的文件描述符标识该文件,将其作为参数传送给read或write。在POSIX应用程序中,整数0、1、2应被代换成符号常数:STDIN_FILENO(标准输入,默认是键盘)STDOUT_FILENO(标准输出,默认是屏幕)STDERR_FILENO(标准错误输出,默认是屏幕)这些常数都定义在头文件<unistd.h>中,文件描述符的范围是0~OPEN_MAX。早期的UNIX版本采用的上限值是19(允许每个进程打开20个文件),现在很多系统则将其增加至256。可用的文件I\O函数很多,包括:打开文件,读文件,写文件等。大多数Linux文件I\O只需要用到5个函数:open,read,write,lseek以及close。
基本API学习
1.open需要包含的头文件:<sys/types.h>,
<sys/stat.h>,
<fcntl.h>函数原型:
intopen(conststr*pathname,intoflag,[...,mode_tmode])功能:打开文件返回值:成功则返回文件描述符,出错返回-1参数:pathname:打开或创建的文件的全路径名oflag:可用来说明此函数的多个选择项,详见后。mode:对于open函数而言,仅当创建新文件时才使用第三个参数,表示新建文件的权限设置。详解oflag参数:oflag参数由O_RDONLY(只读打开)、O_WRONLY(只写打开)、O_RDWR(读写打开)中的一个于下列一个或多个常数O_APPEND:追加到文件尾O_CREAT:若文件不存在则创建它。使用此选择项时,需同时说明第三个参数mode,用其说明新闻件的访问权限O_EXCL:如果同时指定O_CREAT,而该文件又是存在的,报错;也可以测试一个文件是否存在,不存在则创建。O_TRUNC:如果次文件存在,而且为读写或只写成功打开,则将其长度截短为0O_SYNC:使每次write都等到物理I\O操作完成。用open创建一个文件:open.c
#include<stdio.h> #include<stdlib.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #defineFILE_PATH"./test.txt" intmain(void) { intfd; if((fd=open(FILE_PATH,O_RDWR|O_CREAT|O_EXCL,0666))<0){ printf("openerror\n"); exit(-1); }else{ printf("opensuccess\n"); } return0; }如果当前目录下以存在test.txt,屏幕上就会打印“openerror”;不存在则创建该文件,并打印“opensuccess”。2.read需要包含的头文件:<unistd.h>函数原型:
ssize_tread(intfd,void*buf,size_tcount)功能:从打开的文件中读取数据。返回值:实际读到的字节数;已读到文件尾返回0,出错的话返回-1,ssize_t是系统头文件中用typedef定义的数据类型相当于signedint参数:fd:要读取的文件的描述符buf:得到的数据在内存中的位置的首地址count:期望本次能读取到的最大字节数。size_t是系统头文件中用typedef定义的数据类型,相当于unsignedint。3.write需要包含的头文件:
<unistd.h>函数原型:
ssize_twrite(intfd,constvoid*buf,size_tcount)功能:向打开的文件写数据返回值:写入成功返回实际写入的字节数,出错返回-1。不得不提的是,返回-1的常见原因是:磁盘空间已满,超过了一个给定进程的文件长度。参数:fd:要写入文件的文件描述符buf:要写入文件的数据在内存中存放位置的首地址count:期望写入的数据的最大字节数。read和write使用范例:
#include<stdio.h> #include<stdlib.h> #include<unistd.h> intmain(void) { charbuf[100]; intnum=0; //获取键盘输入,还记得POSIX的文件描述符吗? if((num=read(STDIN_FILENO,buf,10))==-1){ printf("readerror"); error(-1); }else{ //将键盘输入又输出到屏幕上 write(STDOUT_FILENO,buf,num); } return0; }4.close需要包含的头文件:
<unistd.h>函数原型:
intclose(intfiledes)功能:关闭一个打开的文件参数:需要关闭文件的文件描述符。当一个进程终止的时候,它所有的打开文件都是由内核自动关闭。很多程序都使用这一功能而不显式地调close关闭一个已打开的文件。但是,作为一名优秀的程序员,应该显式的调用close来关闭已不再使用的文件。5.lseek每个打开的文件都有一个“当前文件偏移量”,是一个非负整数,用以度量从文件开始处计算的字节数。通常,读写操作都是从当前文件偏移量处开始,并使偏移量增加所读或写的字节数。默认情况下,你打开一个文件(open),除非指定O_APPEND参数,不然位移量被设为0。需要包含的头文件:
<sys/types.h>,
<unistd.h>函数原型:
off_tlseek(intfilesdes,off_toffset,intwhence)功能:设置文件内容读写位置返回值:成功返回新的文件位移,出错返回-1;同样off_t是系统头文件定义的数据类型,相当于signedint参数:whence是SEEK_SET,那么该文件的位移量设置为据文件开始处offset个字节whence是SEEK_CUR,那么该文件的位移量设置为当前值加offset。offset可为正或负whence是SEEK_END,那么该文件的位移量设置为文件长度加offset。offset可为正或负
#include<stdio.h> #include<stdlib.h> #include<sys/types.h> #include<unistd.h> #include<fcntl.h> intmain(intargc,char*argv[]) { intfd; charbuf[100]; if((fd=open(argv[1],O_RDONLY))<0){ perror("open"); exit(-1); } read(fd,buf,1); write(STDOUT_FILENO,buf,1); lseek(fd,2,SEEK_CUR); read(fd,buf,1); write(STDOUT_FILENO,buf,1); lseek(fd,-1,SEEK_END); read(fd,buf,1); write(STDOUT_FILENO,buf,1); lseek(fd,0,SEEK_SET); read(fd,buf,1); write(STDOUT_FILENO,buf,1); close(fd); printf("\n"); return0; }6.select之前的read函数可以监控一个文件描述符(eg:键盘)是否有输入,当键盘没有输入,read将会阻塞,直到用户从键盘输入为止。用相同的方法可以监控鼠标是否有输入。但想同时监控鼠标和键盘是否有输入,这个方法就不行的了。
///dev/input/mice是鼠标的设备文件 fd=open("/dev/input/mice",O_RDONLY); read(0,buf,100); read(fd,buf,100);在上面的程序中,当read键盘的时候,若无键盘输入则程序阻塞在第2行,此时即使鼠标有输入,程序也没有机会执行第3行获得鼠标的输入。这种情况就需要select同时监控多个文件描述符。需要包含的头文件:
<sys/select.h>函数原型:
intselect(intmaxfd,fd_set\*readset,fd_set\*writeset,fd_set\*exceptset,conststructtimeval\*timeout)返回值:失败返回-1,成功返回readset,writeset,exceptset中所有,有指定变化的文件描述符的数目(若超时返回0)参数:maxfd:要检测的描述符个数,因此值应为最大描述符+1readset:被监控是否有输入的文件描述符集。不监控时,设为NULLwriteset:被监控是否可以输入的文件描述符集。不监控时,设为NULLexceptset:被监控是否有错误产生的文件描述符集。不监控时,设为NULLtimeval:监控超时时间。设置为NULL表示一直阻塞到有文件描述符被监控到有指定变化。readset,writeset,exceptset这三个描述符集指针均是值—结果参数,调用的时候,被监控描述符相应位需要置1;返回时,未就绪的描数字相应位会被清0,而就绪的会被置1。下面的系统定义的宏,和select配套使用FD_ZERO(&rset):将文件描述符集rset的所有位清0FD_SET(4,&reset):设置文件描述符集rset的bit4FD_CLR(fileno(stdin),&rset):将文件描述符集rset的bit0清0FD_ISSET(socketfd,&rset):若文件描述符集rset中的socketfd位置1
#include<stdio.h> #include<sys/select.h> #include<fcntl.h> #include<unistd.h> #defineMAXNUM100 #defineOPEN_DEV"/dev/input/mice" intmain(void) { fd_setrfds; structtimevaltv; intretval,fd; charbuf[MAXNUM]; fd=open(OPEN_DEV,O_RDONLY); while(1){ FD_ZERO(&rfds); FD_SET(0,&rfds); FD_SET(fd,&rfds); tv.tv_sec=5; tv.tv_usec=0; retval=select(fd+1,&rfds,NULL,NULL,&tv); if(retval<0) printf("error\n"); if(retval==0) printf("Nodatawithin5seconds\n"); if(retval>0){ if(FD_ISSET(0,&rfds)){ printf("Dataisavailablefromkeyboardnow\n"); read(0,buf,MAXNUM); } if(FD_ISSET(fd,&rfds)){ printf("Dataisavailablefrommousenow\n"); read(fd,buf,MAXNUM); } } } return0; }
stat的使用
Linux有个命令,ls-l,效果如下:
<sys/types.h>,
<sys/stat.h>,
<unistd.h>函数原型:
intstat(constchar\*path,structstat\*buf)功能:查看文件或目录属性。将参数path所指的文件的属性,复制到参数buf所指的结构中。参数:path:要查看属性的文件或目录的全路径名称。buf:指向用于存放属性的结构体。stat成功调用后,buf的各个字段将存放各个属性。structstat是系统头文件中定义的结构体,定义如下:
structstat{ dev_tst_dev; ino_tst_ino; mode_tst_mode; nlink_tst_nlink; uid_tst_uid; gid_tst_gid; dev_tst_rdev; off_tst_size; blksize_tst_blksize; blkcnt_tst_blocks; time_tst_atime; time_tst_mtime; time_tst_ctime; };st_ino:节点号st_mode:文件类型和文件访问权限被编码在该字段中st_nlink:硬连接数st_uid:属主的用户IDst_gid:所属组的组IDst_rdev:设备文件的主、次设备号编码在该字段中st_size:文件的大小st_mtime:文件最后被修改时间返回值:成功返回0;失败返回-1
#include<stdio.h> #include<stdlib.h> #include<sys/stat.h> #include<sys/types.h> #include<unistd.h> intmain(intargc,char**argv) { structstatbuf; if(argc!=2){ printf("Usage:stat<pathname>"); exit(-1); } if(stat(argv[1],&buf)!=0){ printf("staterror."); exit(-1); } printf("#i-node:%ld\n",buf.st_ino); printf("#link:%d\n",buf.st_nlink); printf("UID:%d\n",buf.st_uid); printf("GID:%d\n",buf.st_gid); printf("Size%ld\n",buf.st_size); exit(0); }2.文件类型的判定structstat中有个字段为
st_mode,可用来获取文件类型和文件访问权限,我们将陆续学到从该字段解码我们需要的文件信息。st_mode中文件类型宏定义:
#include<stdio.h> #include<stdlib.h> #include<sys/stat.h> #include<sys/types.h> #include<unistd.h> intmain(intargc,char**argv) { structstatbuf; char*file_mode; if(argc!=2){ printf("Usage:stat<pathname>\n"); exit(-1); } if(stat(argv[1],&buf)!=0){ printf("staterror.\n"); exit(-1); } if(S_ISREG(buf.st_mode)) file_mode="-"; elseif(S_ISDIR(buf.st_mode)) file_mode="d"; elseif(S_ISCHR(buf.st_mode)) file_mode="c"; elseif(S_ISBLK(buf.st_mode)) file_mode="b"; printf("#i-node:%ld\n",buf.st_ino); printf("#link:%d\n",buf.st_nlink); printf("UID:%d\n",buf.st_uid); printf("GID:%d\n",buf.st_gid); printf("Size%ld\n",buf.st_size); printf("mode:%s\n",file_mode); exit(0); }
目录操作
当目标是目录而不是文件的时候,ls-l的结果会显示目录下所有子条目的信息,怎么去遍历整个目录呢?答案马上揭晓!1.打开目录需要包含的头文件:<sys/types.h>,
<dirent.h>
函数原型:DIR*opendir(constchar*name)
#include<stdio.h>#include<stdlib.h>#include<dirent.h>intmain(intargc,char*argv[]){DIR*dp;structdirent*entp;if(argc!=2){printf("usage:showdirdirname\n");exit(0);}if((dp=opendir(argv[1]))==NULL){perror("opendir");exit(-1);}while((entp=readdir(dp))!=NULL)printf("%s\n",entp->d_name);closedir(dp);return0;}
相关文章推荐
- centos7安装vlc播放器
- U盘安装centos7
- 安装CentOS 6.7以及CentOS 7.1
- Linux编辑器
- VM Virtualbox安装CentOS 6.7
- Linux 命令 - 关机重启命令 shutdown
- GNOME Linux 桌面入门
- CentOs 6.5 上源码编译安装PHP5.6
- Linux下随机10字符病毒的清除
- 关于mysql官网下载不了Linux版本的问题
- Linux 系统挂载数据盘
- Linux jdk1.7 各个版本 在线安装地址
- linux 三个特权位
- Android (Linux) Suspend流程
- linux 命令 - 打包命令 tar
- 安装linux各种桌面环境
- linux下hwclock及clock命令详解
- Linux第三天
- centOS6.6升级gcc4.8
- centOS6.6升级gcc4.8