1、文件描述符:意思就是unix 环境下用open函数打开一个文件,正确执行后会返回个整型数值,这个就叫文件描述符。(个人理解的,解释可能完全不对)
基本的三种文件描述符:STDIN_FILENO (0)标准输入,STDOUT_FILENO(1) 标准输出,STDERR_FILENO(2) 标准错误输出。
常量的定义基本上都在<unistd.h>头文件中。
2、函数介绍:
2.1 open函数
原型:#include<fcntl.h>
int open(const char *filename, int oflag, mode_t mode) 打开文件
oflag主要参数:O_RDONLY只读打开,O_WRONLY只写打开,O_RDWR读写打开,O_APPEND每次写入追加到文件末端,O_CREAT打开文件不存在则建立,O_TRUNC若文件存在且以只读或读写打开则将该文件长度截短为0
可以用open(filename,O_WRONLY|O_TRUNC|O_CREAT,mode)来新建一个文件。
2.2 creat函数
#include <fcntl.h>
int creat(const char*filename, mode_t mode) 创建新文件
2.3 close函数
int close(int filedes)
2.4 lseek函数
off_t lseek(int filedes,off_t offset, int whence) 为打开的文件设置偏移量
whence参数:SEEK_SET(0)偏移量设置为文件开始处offset个字节,SEEK_CUR(1)偏移量设置为当前值加offset,offset正负皆可,SEEK_END(2)偏移量设置为文件长度加offset,正负皆可。
2.5 read函数
size_t read(int filedes, void *buf, size_t nbytes) 读取文件中内容
2.6 write函数
size_t write(int filedes, const void *buf, size_t nbytes) 将buf中的字符串写到文件中
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <error.h>
int main(){
char buf[64];
if(getcwd(buf,sizeof(buf)-1) != NULL)//得到当前文件目录
printf("%s\n",buf);
else
perror("error");
int fd;
char filename[128];
memset(filename,0,sizeof(filename));
strcat(filename,buf);
strcat(filename,"/3_1_file.txt");
printf("%s\n",filename);
memset(buf,0,sizeof(buf));
if((fd = open(filename,O_WRONLY | O_CREAT | O_TRUNC,0644)) == -1)//创建新文件
perror("Can't open file");
else{
gets(buf);//等待输入
write(fd,buf,sizeof(buf));//写入到文件,文件总共64个字节
off_t of1,of2;
close(fd);
if((fd = open(filename,O_RDONLY)) != -1){
read(fd,buf,64);
printf("File content: %s\n",buf);
of1 = lseek(fd,2,SEEK_SET);//从文件开始偏移2个字节
read(fd,buf,64);//读取64个字节,这时文件的偏移量已经到文件末尾了
printf("File content: %s\n",buf);
of2 = lseek(fd,-60,SEEK_CUR);//从当前文件位置(即末尾)向前便宜60个字节
read(fd,buf,64);
printf("File content: %s\n",buf);
printf("of1=%d, of2=%d\n",of1,of2);
close(fd);//关闭文件
}else{
perror("Can't open file");
}
}
return 0;
}
如果想查看写入到3_1_file.txt中的文件内容,最好使用od -c ./3_1_file.txt
3、I/O效率
这个应该是设置BUFFSIZE=系统block大小应该I/O效率是最高的,一般block大小都是4096bytes
4、复制文件描述符函数
int dup(int fildes);
int dup2(int fildes, int fildes2);
dup返回的新文件描述符是当前可用文件描述符中最小值,dup2则是用fildes2参数指定新文件描述符的数值,若fildes2打开则关闭,若fildes等于fildes2则不关闭,返 回fildes2.在CGI程序用dup2将文件描述符重新定位到标准输入和标准输出。即:dup2(fd,STDOUT_FILENO)或dup2(fd,STDIN_FILENO)。
5、sync、fsync、fdatasync函数
int fsync(int filedes)
int fdatasync(int filedes)
void sync(void)
此三个函数都是将高速缓存中的已经修改的的内容写到硬盘上,用数据库的话说就是防止出现“读脏数据”。
6、改变已打开文件的性质函数:
int fcntl(int fd, int cmd, ... /* arg */ ); //此函数功能很强大
函数功能:
复制一个现有的描述符(cmd=F_DUPFD)
获得或设置文件描述符(cmd=F_GETFD|F_SETFD)
获得或设置文件状态标志(cmd=F_GETFL|F_SETFL)
获得或设置异步I/O所有权(cmd=F_GETOWN|F_SETOWN)
获得或设置记录锁(cmd=F_GETLK|F_SETLK、F_SETLKW)
可以用fcntl函数设置文件状态,常用设置套接字描述符为非阻塞O_NONBLOCK。
dup(filedes)等价于:fcntl(filedes,F_DUPFD,0)
dup2(filedes1,filedes2)等价于:close(filedes2)fcntl(filedes,F_DUPFD,filedes2) 唯一的不同是dup2是原子操作
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc,char* argv[])
{
int val;
if(argc != 2)
{
printf("usage: a.out <descriptor#>\n");
exit(-1);
}
val = fcntl(atoi(argv[1]),F_GETFL,0);
if(val == -1)
{
perror("fcntl() error");
exit(-1);
}
switch(val & O_ACCMODE)
{
case O_RDONLY:
printf("read only.\n");
break;
case O_WRONLY:
printf("write only\n");
break;
case O_RDWR:
printf("read write.\n");
break;
default:
printf("unknown access mode");
}
if(val&O_APPEND)
printf(",append");
if(val&O_NONBLOCK)
printf(",nonblocking");
putchar('\n');
return 0;
}
7、/dev/fd具体Google一下