1.文件描述符
对于内核而言,所有打开的文件都通过文件描述符来引用,他是一个非负数。当打开一个文件或者创建一个文件的时候,内核向进程返回一个文件描述符,open,creat,read,write等函数是用文件描述符作为参数的,在标准UNIX中,0,1,2是被预先设置好的,一次分别是标准标准输入,标准输出,标准出错。但是按照惯例,应该用符号代替它们,分别表示-STDIN_FILENO,STDOUT_FILENO,STDERR_FILENO,这几个常量都在unistd.h头文件中定义,
PS:文件描述符的变化范围是0~OPEN_MAX-1
1.函数open和openat
#include<unistd.h>
intopen (const char *path,int oflag, ... /*mode_tmode*/);
intopenat(int fd, const char *path, int oflag, .../*mode_tmode*/);
成功返回文件描述符,失败返回-1
path是要打开的文件路径或者名子,oflag为几个选项的组合,
分别是:O_RDONLY(只读)O_WRONLY(只写)O_RDWR(读写)
以上三种比较常用。还有多种参考书62页
两个函数的区别fd参数把open和openat函数区分开
(1)如果path指定的是绝对路径,在这种情况下fd被忽略,二者相等。
(2)path参数指定的是相对路径名,fd参数指定的是相对路径名在文件系统中的开始地址,fd参数是通过打开先谷地路径名所在的目录所获取的。
(3)path参数指定了相对路径名,fd参数具有特殊值AT_FDCWD。在这种情况下,路径名称在当前工作目录中获取。openat函数在操作上与open函数类似。
openat函数是POSIX版本新增加的函数之一。希望解决两个问题,第一,可以通过相对路径名打开目录中的文件,而不再是智能打开当前工作目录,线程的方面会用到此处。
第二可以避免TOCTTOU错误(了解)
2.函数creat
#include<unistd.h>
intcreat (const char *path, mode_t mode);
成功返回文件描述符,失败返回-1
此函数等效与,open(path , O_WRONLY | O_CREAT | O_TRUNC, mode);
creat不推荐使用,因为他是有一个缺陷的,他以只写方式打开创建的文件,最好使用open函数来创建文件。因为操作可以控制。
3.函数close
可以调用close函数来关闭一个打开的文件
#include<unistd.h>
intclose (int fd);
成功返回0,失败返回-1
用完了的文件要记得关闭哦。
记住,当一个进程终止的时候,内核自动关闭它所有的打开文件,很多程序都利用这一功能而不显式的关闭打开文件。
4.函数lseek
每一个打开的文件都有一个与其相关联的“当前文件偏移量”。它通常是一个非负整数,用以度量从文件开始处计算的字节数。
#include<unistd.h>
off_tlseek(int fd, off_t offset, int whence);
成功返回文件的偏移量。失败则返回-1
offset参数和whence参数是有关联的。
*若whence参数是SEEK_SET,则该文件的偏移量设置为距文件开始处offset个字节。
*若whence参数是SEEK_CUR,则该文件的偏移量设置为当前值+offset个字节。offset可以为正,可以为负
*若whence参数是SEEK_END,则该文件的偏移量设置为文件长度+offset个字节。offset可以为正,可以为负
可以用下列方式确定打开文件的当前偏移量:
off_t currpos;
currpos= lseek(fd, 0 ,SEEK_CUR)
这种方法还可以用来确定一个文件是否可以被设置偏移量,如果文件描述符指向的是一个管道,FIFO或者网络套接字,则lseek返回-1并且将error设置为ESPIPE
实例:测试对其标准输入能否设置偏移量
#include“apue.h”
intmain (void) {
if(lseek(STDIN_FILENO,0,SEEK_CUR)== -1)
printf(“cannot seek”);
else
printf(“seekOK \n”);
exit(0);
}
$./a.out < /etc/passwd (这是一个文件,将里面的内容输入到程序中可见可以设置偏移量)
seekOK
$cat < /etc/passwd | ./a.out ( |是一个管道就是将cat出来的东东输入到程序中,可见不可以设置偏移量)
cannotseek
$./a.out< /var/spool/cron/FIFO (可见,FIFO文件不可以设置偏移量)
cannnotseek
PS:通常文件偏移量可以为负,所以测试是否出错的时候请不要测试是否小于0,二要测试是否等于-1
文件偏移量可以大于文件,但是在下一次写操作的时候会在文件中构成一个空洞。空洞是不占用磁盘块的
5.函数read和write
调用read函数从打开的文件中读取数据
#include<unistd.h>
ssize_tread(int fd,void *buf. size_t nbytes);
成功返回读到的字节数,失败返回-1
记住,每一次读取都会使文件偏移量增加,增加数和读取数大小有关,读取多少增加多少。
返回值0表示在文件尾端
#include<unistd.h>
ssize_twrite(int fd,void *buf. size_t nbytes);
二者差不多,一个是写,一个是读取。读取出错原因是磁盘写满,或者超过了一个给定进程的文件长度限制。
实例:只使用read和wtite函数复制一个文件
#include“apue.h”
#defineBUFFSIZE 4096
intmain (void) {
intn;
charbuf[BUFFSIZE];
while(n = read(STDIN_FILENO, buf, BUFFSIZE) > 0)
if(write (STDIN|_FILENO, buf, n) != n)
err_sys(“writeerror”); //apue.h自带的错误处理函数
if (n < 0)
err_sys(“readerror”);
exit(0);
}