stdin & stdout & stderr
open函数
#include
#include
#include
int open(const char *pathname, int flags);
int open (const char *pathname, int flags,mode_t mode);
pathname :要打开的文件或要创建的目标文件
flags:打开文件时,可以传入多个参数选项,用下面的一个或者多个“或”运算,构成flags
参数:
O_RDONLY:只读打开
O_WRONLY:只写打开
O_RDWR:读,写打开
以上三个常量必须存在一个并且有且只有一个
O_CREAT:若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限。
O_APPEND:追加写
返回值:
成功:新打开的文件描述符
失败:-1
open函数具体使用哪个和具体的应用场景相关,如果目标文件不存在,需要open创建,则第三个参数表示创建文件的默认权限,否则,使用两个参数的open。
open函数返回值
1.fopen , fclose , **fread **, fwrite 都是C标准库中的函数,叫C库函数。
2.open,close, read, write ,lseek 都属于系统提供的接口,称为系统调用接口。
通过上图可以发现库函数与系统调用接口是上下级的关系。可以认为,f#系列的函数是对系统调用的封装,方便二次开发。
文件描述符fd
文件描述符是一个小整数
文件描述符是从0开始的小整数,当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件。于是有了file结构体。表示一个已经打开的文件对象。
执行open系统调用,必须要让文件和进程相关联,每个进程都有一个指针*files,指向file_struct,该表最重要的部分就是包含一个指针数组,每个元素都是一个指向打开文件的指针,本质上文件描述符就是该数组的下标,根据文件描述符就可以找到对应的文件。
文件描述符实际上是操作系统对文件的管理。
文件描述符分配规则:从未被使用的最小的开始分配。
重定向的本质
假设关闭fd:1
#include
#include
#include
#include
#include
int main()
{
close(1);
int fd=open("myfile",O_WRONLY|O_CREAT,00644);
if(fd<0)
{
perror("open");
return 1;
}
printf("fd:%d\n",fd);
fflush(stdout);
close(fd);
exit(0);
}
通过代码我们发现,本来应该输出到显示器上的内容,写入到myfile中,其中,fd=1,这叫做输出重定向。
常见的重定向有:>,>>,<
当数组的下标被关闭,open函数调用时默认打开最小未被使用的文件描述符对应的文件。
printf函数是C库中的输入输出函数,一般想stdout中输出,但当stdout访问文件的时候找出的还是fd:1,但此时下标为1表示的内容,已经变成了myfile的地址,不再是显示器文件的地址,所以所有的消息都输出到myfile文件中,进而完成输出重定向。
dup2的系统调用
#include
int dup2(int oldfd, int newfd);
dup2 函数中newfd是oldfd函数的一份拷贝,如果newfd打开先要关闭newfd,如果oldfd不是一个有效的文件描述符,那么调用失败,并且关闭newfd;如果oldfd是一个有效的文件描述符,且newfd等于oldfd,那么直接返回返回newfd。