进程中文件描述字与文件结构指针的疑问

时间:2022-06-03 17:59:42
刚学linux不久,对下面这两段代码产生的结果有点不解,程序非常简单,希望哪位高手可以给个详细的解答,谢:)
//////////////1,文件描述子
int main()
{
  int fd;
  int pid;
  char msg1[] = "hello\n";
  char msg2[] = "world\n";
  if ((fd=creat("a.txt",0644)) == -1)
    return -1;
  if (write(fd,msg1,strlen(msg1)) == -1)
    return -1;
  if ((pid = fork()) == -1)
    return -1;
  if (write(fd,msg2,strlen(msg2)) == -1)
    return -1;

  close(fd);
  return 0;
}
///////////////2文件结构指针
int main()
{
  FILE *fp;
  int pid;
  char msg1[] = "hello\n";
  char msg2[] = "world\n";
  if ((fp = fopen("a.txt","w")) == NULL)
    return -1;
  fprintf(fp,"%s",msg1);
  if ((pid = fork()) == -1)
    return -1;
   fprintf(fp,"%s",msg2);
  fclose(fp);
  return 0;
}

6 个解决方案

#1


文件指针是标准库定义的,文件描述符是*nix系统里专有的吧

#2


好像不是很清楚啊,有谁能解释一下上面这两个程序的结果为什么是怎样么??

#3


这是因为库IO做了缓存,在fork之前没有正在输出,所以fork时该缓存被复制。你在第二个程序的:
int ((pid = fork()) == -1)前边加上fflush(fp)就可以看出来了。

#4


这个显然么……

fork的时候连带fd一起复制了,而C的标准IO对于文件默认是全缓冲。即除非手动刷新(譬如fseek、fflush等),否则要等缓冲区全满才会调用write来写文件。而在刷新缓冲区之前你fork了,所以造成了缓冲区也被同时复制,所以是两个进程都往文件里面写同样的内容。而且两个内容不会发生重叠,这个是因为内核里面共享了打开的文件,使用的是同一个偏移量。

#5


w r i t e函数是不带缓存的。
因为在f o r k之前调用w r i t e,所以其数据写到标准输出一次。但是,标准I / O库是带缓存的。回
注意:并不是标准I/O就默认是全缓冲,如果标准输出连到终端设备(比如你的屏幕),则它是行缓存的,否则它是全缓存的。
通俗点:
行缓冲,一行完了再输出。
全缓冲,全部完了再输出。

#6


对不起,我上面的直接复制的书上内容,忘了改了。更改为:
w r i t e函数是不带缓存的。
因为在f o r k之前调用w r i t e,所以其数据写到对应描述符。但是,标准I / O库是带缓存的。
注意:并不是标准I/O就默认是全缓冲,如果标准输出连到终端设备(比如你的屏幕),则它是行缓存的,否则它是全缓存的。
通俗点:
行缓冲,一行完了再输出。
全缓冲,全部完了再输出。

#1


文件指针是标准库定义的,文件描述符是*nix系统里专有的吧

#2


好像不是很清楚啊,有谁能解释一下上面这两个程序的结果为什么是怎样么??

#3


这是因为库IO做了缓存,在fork之前没有正在输出,所以fork时该缓存被复制。你在第二个程序的:
int ((pid = fork()) == -1)前边加上fflush(fp)就可以看出来了。

#4


这个显然么……

fork的时候连带fd一起复制了,而C的标准IO对于文件默认是全缓冲。即除非手动刷新(譬如fseek、fflush等),否则要等缓冲区全满才会调用write来写文件。而在刷新缓冲区之前你fork了,所以造成了缓冲区也被同时复制,所以是两个进程都往文件里面写同样的内容。而且两个内容不会发生重叠,这个是因为内核里面共享了打开的文件,使用的是同一个偏移量。

#5


w r i t e函数是不带缓存的。
因为在f o r k之前调用w r i t e,所以其数据写到标准输出一次。但是,标准I / O库是带缓存的。回
注意:并不是标准I/O就默认是全缓冲,如果标准输出连到终端设备(比如你的屏幕),则它是行缓存的,否则它是全缓存的。
通俗点:
行缓冲,一行完了再输出。
全缓冲,全部完了再输出。

#6


对不起,我上面的直接复制的书上内容,忘了改了。更改为:
w r i t e函数是不带缓存的。
因为在f o r k之前调用w r i t e,所以其数据写到对应描述符。但是,标准I / O库是带缓存的。
注意:并不是标准I/O就默认是全缓冲,如果标准输出连到终端设备(比如你的屏幕),则它是行缓存的,否则它是全缓存的。
通俗点:
行缓冲,一行完了再输出。
全缓冲,全部完了再输出。