首先我们先来看一下重定向之输出重定向的基本流程理解。
我们需要知道我们的文件描述符是什么了?
通过自己理解浅显不深入的说文件描述符是一个进程指向一个文件结构体(file_struct)数组的下标,当然这个下标也是从0开始的,而且默认打开0,1,2对应的都是这个进程关联控制文件的功能。
- 即分别对应stdin(输入),stdout(输出),stderr(标准错误)。
- 我们的c库函数只是对这些系统调用接口的封装而已,使用起来更加方便。
- 我们可以尝试一下close(0),close(1),close(2)简单看一下,默认打开文件描述符的个数变化。
这里我们close(1)一下,这样就进入了我们输出重定向的话题了。
来段代码:
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlibh>
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(fd);
close(fd);
exit(0);
exit(0);
}
此时发现本应该输出到显示器的内容,输出到文件myfile当中,其中,fd = 1.
在来看一段代码
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
int mian()
{
const char * msg0 = "hello printf\n";
const char *mag1 = "hello fwrite\n";
const char *msg2 = "hello write\n";
printf("%s", msg0);
fwrite(msg1, strlen(msg0), 1, stdout);
write(1, msg2, strlen(msg2));
fork();
return 0;
}
运行结果:
hello printf
hello fwrite
hello write
但是当我们对运行中的进程进程进行了重定向close(1),运行结果是这样的:
hello write
hello printf
hello fwrite
hello printf
hello fwrite
我们发现write之调用了一次,其他两个调用了,两次,这个结果可以大胆的用脑壳想一下,肯定是和进程有一定关系的,没错深入思考的确如此。
- [一般c库文件,调0时候stdin时候是全缓存,而写入显示器是行缓存 ]
- [库函数自带缓存区,当发生重定向时候,当发生重定向到普通文件时候,数据有以前1(stdout)的行缓存变成了全缓存]
- [但是我们放入缓存区中的数据,并不会被立马刷新,甚至在子进程之后。]
- [但是进程退出以后会统一,刷新,写入文件当中]
- [fork时候会发生一个写时拷贝,所以当父进程刷新的时候子进程也有和父进程相同的数据,随机产生了两份数据]
- [write没有变换因为write是系统函数,在系统层没有缓存区的存在]
所以简单的说了:printf fwrite C库函数自带缓存区,系统函数没有。而这个缓存区是对系统调用的一个封装,prinft,fwrite有,系统里面的接口函数没有。所以有C标准库提供。