在Linux中,write是不带缓冲区的函数,也就是其写完以后不会在缓冲区中存储,直接写出。
考虑以下代码
1、使用fputs
# include <unistd.h>
# include <stdio.h>
# include <stdlib.h>
# include <errno.h>
int main(void)
{
FILE *stream;
if ((stream = fopen ( "./log.txt" , "a" )) == NULL) //打开文件流
{
printf( "error: %d\n" , errno);
exit (1);
}
char buf[20]="hello world";
fputs ( buf , stream);//带缓冲区的写
sleep(20);
return 0;
}
由于fputs是带缓冲区的写,而文件流默认是全缓冲,那么程序执行结果如下:
在sleep(20)之前:
可以看到,根本没有数据写入
sleep(20)之后,即程序结束后:
只有程序执行完,全缓冲内容才写入进去。
2、使用write
write是不带缓冲的
# include <unistd.h>
# include <stdio.h>
# include <stdlib.h>
# include <errno.h>
# include <fcntl.h>
# include<string.h>
int main(void)
{
int fd;
if ((fd = open ( "./log.txt" , O_WRONLY )) == -1) {
//以只写方式打开文件描述符,
printf( "error: %d\n" , errno);
exit (1);
}
char buf[20]="hello world";
write(fd,buf,strlen(buf));
//write写的是文件描述符
//注意:这里用strlen,返回的是11,即字符串长度
//如果用sizeof(),返回的是20,即数组长度
//如果是buf[]="hello world",那么用strlen返回的仍然是11,
//但是用sizeof返回的却是12,因为buf[]会自动在末尾加上'\0',而sizeof会算进去这个'\0',但是strlen却不会
sleep(20);
return 0;
}
执行结果:
sleep之前打开文件
可以看到,write完立刻就有数据输出
3、Linux的进程缓冲区拷贝
在《Unix环境高级编程第三版》183页有这么一个程序:
#include <unistd.h>
#include <stdio.h>
#include <error.h>
#include <stdlib.h>
int globvar=6;
char buf[]="a write to stdout\n";
int main(int argc,char *argv[])
{
int var;
pid_t pid;
var=88;
if(write(STDOUT_FILENO,buf,sizeof(buf)-1)!=sizeof(buf)-1)
{
return 0;
}
printf("before fork\n");
if((pid=fork())<0)
{
printf("fork error\n");
exit(0);
}
else if(pid==0)//zi jin cheng
{
globvar++;
var++;
}
else
{
sleep(20);//zhu jin cheng
}
printf("pid = %ld, glob = %d, var = %d\n",(long)getpid(),globvar,var);
return 0;
}
如果在终端中执行:
如果执行终端改为文件:
先是(sleep之前):
立即出现write结果,这是因为write无缓冲,立即打印输出,而这个before fork是子线程结束打印出的。
然后(sleep 之后)
可以看到,如果打印到文件,会打印两个“before fork”,第二个是主线程打印出来的。
这是因为printf会打印到缓冲区,而文件缓冲是全缓冲,进程拷贝会把缓冲区也拷贝,在进程结束后打印到文件中去。