首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 操作系统 > UNIXLINUX >

关于fork,系统调用,库函数的有关问题

2012-05-22 
关于fork,系统调用,库函数的问题一段很简单的输入字符到文件的代码,先是使用系统调用:C/C++ code#include

关于fork,系统调用,库函数的问题
一段很简单的输入字符到文件的代码,先是使用系统调用:

C/C++ code
#include <stdlib.h>#include <stdio.h>#include <string.h>int main(){       int fd;       int pid;       char msg1[]="Test 1 2 3 ..\n";       char msg2[]="Hello,  hello\n";       if((fd=creat("testfile",0644))==-1)               return 0;       if(write(fd,msg1,strlen(msg1))==-1)               return 0;       if((pid=fork())==-1)               return 0;       if(write(fd,msg2,strlen(msg2))==-1)               return 0;       close(fd);       return 1;}

执行后结果:
C/C++ code
Test 1 2 3 ..Hello,  helloHello,  hello


再使用c的库函数重写该程序:
C/C++ code
#include <stdio.h>#include <stdlib.h>int main(){        FILE *fp;        int pid;        char msg1[]="Test 1 2 3 ...";        char msg2[]="Hello,   hello";        if((fp=fopen("testfile2","w"))==NULL)                return 0;        fprintf(fp,"%s      pid:%d\n",msg1,getpid());        if((pid=fork())==-1)                return 0;        fprintf(fp,"%s      pid:%d\n",msg2,getpid());        fclose(fp);        return 1;}

执行后结果是:
C/C++ code
Test 1 2 3 ...      pid:8795Hello,   hello      pid:8795Test 1 2 3 ...      pid:8795Hello,   hello      pid:8796

为什么使用库函数的时候父进程会打印三次,我完全不能理解。

[解决办法]
因为FILE对于文件使用 _IOFBF 全缓冲, \n是不会冲刷buffer的。

所以fork后,子进程的fp->buffer里的内容就是父进程写出的但还留在buffer里的内容,子进程继续fprintf就是追加到buffer,最后父子进程分别关闭,各自冲刷各自的2行数据,一共4行。
[解决办法]
fprintf只是写到磁盘缓冲里,并没有写磁盘文件. 
在fprintf后面加一句fflush(fp);(fp是你的文件指针)就可以了
fprintf的确每fork一个进程才写一次,因为必须写满缓冲后再批量写磁盘的原因,你会感觉文件是批量生成的.

[解决办法]
C/C++ code
#include <stdio.h>#include <stdlib.h>int main(){        FILE *fp;        int pid;        char msg1[]="Test 1 2 3 ...";        char msg2[]="Hello,   hello";        if((fp=fopen("testfile2","w"))==NULL)                return 0;        fprintf(fp,"%s      pid:%d\n",msg1,getpid());        fflush(fp);                   //这样就好了        if((pid=fork())==-1)                return 0;        fprintf(fp,"%s      pid:%d\n",msg2,getpid());        fclose(fp);        return 1;}
[解决办法]
说的再细一点吧:
fprintf只是写到磁盘缓冲里,fork之后,连带这个磁盘缓冲也一起复制了,而且还不输出,直到fclose(fp)了,才强制刷新磁盘缓冲区,写进磁盘文件。
可以,在fclose(fp)前加个sleep(20);然后在这20秒内看testfile2,不会发现什么也没有,20秒后就一次性全都写进去了。

热点排行