文件描述符
对于Linux内核而言,所有的文件或设备都对应一个文件描述符(Linux的设计哲学:一切皆文件),这样可以简化系统编程的复杂程度;
当打开/创建一个文件的时候,内核向进程返回一个文件描述符(是一个非负整数).后续对文件的操作只需通过该文件描述符即可进行,内核记录有关这个打开文件的信息;
一个进程启动时,默认已经打开了3个文件,标准输入(0,STDIN_FILENO),标准输出(1,STDOUT_FILENO),标准错误输出(2,STDERR_FILENO),这些常量定义在unistd.h头文件中;
其中,文件描述符基本上是与文件描述指针(FILE*)一一对应的,如文件描述符0,1,2对应stdin,stdout,stderr;
文件指针与文件描述符的转换
fileno:将文件指针转换成文件描述符
intfileno(FILE*stream);
fdopen:将文件描述符转换成文件指针
FILE*fdopen(intfd,constchar*mode);
//示例int main(){cout << "fileno(stdin) = " << fileno(stdin) << endl;cout << "fileno(stdout) = " << fileno(stdout) << endl;cout << "fileno(stderr) = " << fileno(stderr) << endl;return 0;}文件I/OAPI
1.open
#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int open(const char *pathname, int flags);int open(const char *pathname, int flags, mode_t mode);
参数:
pathname:文件名,可以包含[绝对/相对]路径名;
flags:文件打开模式;
mode:用来指定对文件所有者,文件用户组以及系统中的其他用户的访问权限;
注意:newMode=mode&~umask
flags常用值
//示例1int main(){int fd = open("test.txt", O_RDONLY);if (fd == -1){cerr << "file open error, errno = " << errno <<"\nstrerror: " << strerror(errno) << endl;perror("perror");exit(EXIT_FAILURE);}cout << "file open success" << endl;}//示例2inline void err_exit(std::string message){perror(message.c_str());exit(EXIT_FAILURE);}int main(){umask(0000);int fd = open("test.txt", O_RDWR|O_CREAT|O_EXCL, 0666);if (fd == -1)err_exit("file open error");elsecout << "file descriptor = " << fd << endl;}
[附]
(1).umaskAPI
//改变umask值
mode_tumask(mode_tmask);
(2).ulimit-a
查看系统中的各种限制;
其中-n:查看一个进程所能够打开的最大文件数
(3).cat/proc/sys/fs/file-max
查看一个系统能够支持的最大打开文件数(该数与内存大小有关)
2.close
#include <unistd.h>int close(int fd);
write会等到将buf的内容真正的写入到磁盘才真正返回;
//示例: 带有O_SYNC选项int main(int argc, char *argv[]){if (argc < 3){cerr << "Usage : " << argv[0] << " src dest" << endl;exit(EXIT_FAILURE);}int infd = open(argv[1], O_RDONLY);if (infd == -1)err_exit("file O_RDONLY error");int outfd = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC|O_SYNC, 0666);if (outfd == -1)err_exit("file O_WRONLY error");char buf[1024];int readBytes, writeBytes;while ((readBytes = read(infd, buf, sizeof(buf))) > 0){writeBytes = write(outfd, buf, readBytes);cout << "readBytes = " << readBytes<< ", writeBytes = " << writeBytes << endl;}}文件的随机读写
5.lseek
对应于C库函数中的fseek,通过指定相对于当前位置,末尾位置或开始位置的字节数来重定位currp:
off_t lseek(int fd, off_t offset, int whence);
返回值:新的文件偏移值;
Whence取值:
SEEK_SET
Theoffsetissettooffsetbytes.
SEEK_CUR
Theoffsetissettoitscurrentlocationplusoffsetbytes.
SEEK_END
怎么能研究出炸药呢?爱迪生不经历上千次的来自失败,怎么能发明电灯呢