I/O -x open()-read()-write()-close()-lseek()
大多数unix文件I/O只需要用到5个函数:open,read,write,lseek,close。这些函数都为不带缓存的I/O,不带缓存指的是每个read和write都调用内核中的一个系统调用。这些函数使用时要用到三个头文件:sys/types.h,sys/stat.h,fcntl.h
open函数:int open(const char path *name, int oflag,...);
返回:若成功为只写打开的文件描述符,若错误为-1。
调用open函数可以打开或创建一个文件,仅当创建新文件时才使用第三个参数,由open函数返回的文件描述符一定是最小的未用的描述符数字。
第一个参数为路径名
第二个参数为文件状态标志:
O_RDONLY或0:可读
O_WRONLY或1:可写
O_RDWR或2:可执行
O_APPEND:每次写时都加到文件的尾部
O_CREAT:若此文件不存在则创建它,使用此选项时,需同时说明第三个参数mode,用其说明该新文件的存取许可权位
O_EXCL:如果同时指定了O_CREAT,而文件已经存在,则出错,这可测试一个文件是否存在,如果不存在则创建此文件成为一个原子操作
O_TRUNC:如果此文件存在,而且为只读或只写成功打开,则将其长度截短为0
O_NOCTTY:如果pathname指的是终端设备,则不将此设备分配作为此进程的控制终端
O_NONBLOCK:如果pathname指的是一个FIFO,一个块特殊文件或一个字符特殊文件,则此选择项为此文件的本次打开操作和后续的I/O操作设置非阻塞方式
O_SYNC:使每次write都等到物理I/O操作完成
第三个参数一般为文件权限:
S_IRWXU,0700:代表该文件所有者具有可读,可写,可指向的权限
S_IRUSR或S_IREAD,0400:代表该文件所有者具有可读取的权限
S_IWUSR或S_IWRITE,0200:代表该文件所有者具有可写入的权限
S_IXUSR或S_IEXEC,0100:代表该文件所有者具有可指向的权限
S_IRWXG,0070:代表该文件用户组具有可读,可写,可执行的权限
S_IRGRP,0040:代表该文件用户组具有可读的权限
S_IWGRP,0020:代表该文件用户组具有可写的权限
S_IXGRP,0010:代表该文件用户组具有可执行的权限
S_IRWXO,0007:代表其他用户具有可读,可写,可执行的权限
S_IROTH,0004:代表其他用户具有可读的权限
S_IWOTH,0002:代表其他用户具有可写的权限
S_IXOTH,0001:代表其他用户具有可执行的权限
creat函数:int creat(const char *pathname, mode_t mode);
返回:若成功为只写打开的文件描述符,若出错为-1
该函数等效于:open(pathname,O_WRONLY|O_CREAT|O_TRUNC,mode);
用于创建一个新文件
read函数 :ssize_t read (int fd, void *buf, size_t count);
返回值
成功返回读取的字节数,出错返回-1并设置errno,如果在调read之前已到达文件末尾,则这次read返回0。
参数
参数count是请求读取的字节数,读上来的数据保存在缓冲区buf中,同时文件的当前读写位置向后移。
注意这个读写位置和使用C标准I/O库时的读写位置有可能不同,这个读写位置是记在内核中的,而使用C标准I/O库时的读写位置是用户空间I/O缓冲区中的位置。
比如用fgetc读一个字节,fgetc有可能从内核中预读1024个字节到I/O缓冲区中,再返回第一个字节,这时该文件在内核中记录的读写位置是1024,而在FILE结构体中记录的读写位置是1。注意返回值类型是ssize_t,表示有符号的size_t,这样既可以返回正的字节数、0(表示到达文件末尾)也可以返回负值-1(表示出错)。
read函数返回时,返回值说明了buf中前多少个字节是刚读上来的。有些情况下,实际读到的字节数(返回值)会小于请求读的字节数count,例如:读常规文件时,在读到count个字节之前已到达文件末尾。例如,距文件末尾还有30个字节而请求读100个字节,则read返回30,下次read将返回0。
1 #include <stdio.h> 2 #include <io.h> 3 #include <alloc.h> 4 #include <fcntl.h> 5 #include <process.h> 6 #include <sys\stat.h> 7 int main(void) 8 { 9 void* buf ; 10 int handle; 11 int bytes ; 12 buf=malloc(10); 13 /* 14 LooksforafileinthecurrentdirectorynamedTEST.$$$andattempts 15 toread10bytesfromit.Tousethisexampleyoushouldcreatethe 16 fileTEST.$$$ 17 */ 18 handle=open("TEST.$$$",O_RDONLY|O_BINARY,S_IWRITE|S_IREAD); 19 if(handle==-1) 20 { 21 printf("ErrorOpeningFile\n"); 22 exit(1); 23 } 24 bytes=read(handle,buf,10); 25 if(bytes==-1) 26 { 27 printf("ReadFailed.\n"); 28 exit(1); 29 } 30 else 31 { 32 printf("Read:%dbytesread.\n",bytes); 33 } 34 return0 ; 35 }
write(将数据写入已打开的文件内)
表头文件
#include<unistd.h>
定义函数
ssize_t write (int fd,const void * buf,size_t count);
函数说明
write()会把指针buf所指的内存写入count个字节到参数fd所指的文件内。当然,文件读写位置也会随之移动。
返回值
如果顺利write()会返回实际写入的字节数。当有错误发生时则返回-1,错误代码存入errno中。
错误代码
EINTR 此调用被信号所中断。
EAGAIN 当使用不可阻断I/O 时(O_NONBLOCK),若无数据可读取则返回此值。
EBADF 参数fd非有效的文件描述词,或该文件已关闭。
函数名: write
功 能: 写到一文件中
用 法: int write(int handle, void *buf, int nbyte);
程序例:
1 #include<stdlib.h> 2 #include<unistd.h> 3 #include<stdio.h> 4 #include<string.h> 5 #include<fcntl.h> 6 #include<errno.h> 7 intmain(void) 8 { 9 inthandle; 10 charstring[40]; 11 intlength,res; 12 /* 13 Createafilenamed"TEST.$$$"inthecurrentdirectoryandwrite 14 astringtoit.If"TEST.$$$"alreadyexists,itwillbeoverwritten. 15 */ 16 if((handle=open("TEST.$$$",O_WRONLY|O_CREAT|O_TRUNC, 17 S_IREAD|S_IWRITE))==-1) 18 { 19 printf("Erroropeningfile.\n"); 20 exit(1); 21 } 22 23 strcpy(string,"Hello,world!\n"); 24 length=strlen(string); 25 26 if((res=write(handle,string,length))!=length) 27 { 28 printf("Errorwritingtothefile.\n"); 29 exit(1); 30 } 31 32 printf("Wrote%dbytestothefile.\n",res); 33 close(handle); 34 return0; 35 }
1 structxfcb{ 2 charxfcb_flag;/*Contains0xfftoindicatexfcb*/ 3 charxfcb_resv[5];/*ReservedforDOS*/ 4 charxfcb_attr;/*Searchattribute*/ 5 structfcbxfcb_fcb;/*Thestandardfcb*/ 6 };
名称 : write
使用权限 : 所有使用者
使用方式 :
write user [ttyname]
说明 : 传讯息给其他使用者
user : 预备传讯息的使用者帐号
ttyname : 如果使用者同时有两个以上的 tty 连线,可以自行选择合适的 tty 传讯息
例子.1 :
传讯息给 Rollaend,此时 Rollaend 只有一个连线 :
write Rollaend
接下来就是将讯息打上去,结束请按 ctrl+c
例子.2 :传讯息给 Rollaend,Rollaend 的连线有 pts/2,pts/3 :
write Rollaend pts/2
接下来就是将讯息打上去,结束请按 ctrl+c
注意 : 若对方设定 mesg n,则此时讯息将无法传给对方
close函数:int close(int filedes);
返回:若成功为0,若出错为-1
关闭一个文件时也释放该进程加在该文件上的所有记录锁,当一个进程终止时,它所有的打开文件都由内核自动关闭。
lseek函数:off_t lseek(int filedes, off_t offset, int whence);
返回:若成功为新的文件位移,若出错为-1
每个打开文件都有一个与其相关联的”当前文件位移量”,它是一个非负整数,用以度量从文件开始处计算的字节数。按系统默认,当打开一个文件时,除非指定O_APPEND选项时,否则该位移量被设置为0。通常读,写操作都从当前文件位移量处开始,并使位移量增加所读或写的字节数。可以调用lseek显式地定位一个打开的文件。
对参数offset的解释与参数whence的值有关。
若whence是SEEK_SET,则将该文件的位移量设置为距文件开始处offset个字节
若whence是SEEK_CUR,则将该文件的位移量设置为其当前值加offset,offset可为正或负
若whence是SEEK_END,则将该文件的位移量设置为文件长度加offset,offset可为正或负
早期用0,1,2代铁SEEK_SET,SEEK_CUR,SEEK_END。
某些设备也可能允许负的位移量,但对于普通文件,则其位移量必须是非负值
范例:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <sys/types.h> 4 #include <sys/stat.h> 5 #include <fcntl.h> 6 int main(void) 7 { 8 int fd, size; 9 char buf1[]="Hello, world"; 10 char buf2[50]; 11 if((fd=open("/home/sam/helloworld",O_CREAT|O_TRUNC|O_RDWR,0666))==-1) 12 { 13 printf("Open or create file named \"helloworld\" failed.\n"); 14 exit(1); 15 } 16 write(fd,buf1,sizeof(buf1)); 17 close(fd); 18 if((fd=open("/home/sam/helloworld",O_RDONLY))==-1) 19 { 20 printf("Open file named \"helloworld\" failed.\n"); 21 exit(1); 22 } 23 size=read(fd,buf2,sizeof(buf2)); 24 close(fd); 25 printf("%s\n",buf2); 26 if((fd=open("/home/sam/helloworld",O_RDONLY))==-1) 27 { 28 printf("Open file named \"helloworld\" failed.\n"); 29 exit(1); 30 } 31 lseek(fd,6,SEEK_SET); 32 size=read(fd,buf2,sizeof(buf2)); 33 printf("%s\n",buf2); 34 close(fd); 35 return 0; 36 }
相关函数
fcntl,lseek,sync,fsync,fwrite