是否在fork之后由child创建了文件,也与父共享?

时间:2013-04-19 10:52:16

标签: c linux unix fork

我知道在fork()之后,打开的所有文件(及其偏移)都是共享的 由孩子。也就是说,共享所有文件的文件表条目。

如果孩子打开某个文件会怎样?是否特定于孩子?或者由父母分享?

我也写过小测试程序。这是测试这个的正确方法吗?

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

#define FLAG (O_RDWR | O_CREAT | O_TRUNC)

int main(int argc, char *argv[])
{
    pid_t pid;

    if ((pid = fork()) < 0) {
        perror("fork error");
        exit(1);
    } else if (pid == 0) {
        int fc;
        if ((fc = open("abc", FLAG)) == -1) {
            perror("cannot open abc");
            exit(-1);
        }
        exit(fc);
        //returning the file descriptor open through exit()
    } else {
        int fp;
        wait(&fp);
        if (fp == -1)
            exit(1);
        if (fcntl(fp, F_GETFD) == -1)
            perror("doesn't work");     //Ouputs: doesn't work: Bad file descriptor
        //returns file descriptor flags
        //should not return error, if fd is valid
    }
    return 0;
}

感谢。

4 个答案:

答案 0 :(得分:5)

孩子在fork()时刻获得父母的文件描述符的副本。

如果您在孩子中打开一个文件,则不会与父母共享。

此外,如果您在fork()之后在父进程中打开文件,则不会与该子进行共享。

答案 1 :(得分:0)

当您的子进程退出时,所有剩余的打开文件将被关闭。因此,当父母尝试使用它时,它就不再有效了。

答案 2 :(得分:0)

man fork

  

子进程继承父进程打开文件的副本   描述。   子中的每个文件描述符都指向相同的打开文件   description(参见open(2))作为相应的文件描述符   家长。这意味着两个描述符共享打开文件状态   标志,当前文件偏移和信号驱动的I / O属性(参见   fcntl(2)中的F_SETOWN和F_SETSIG的描述。

如果您关闭子项中的文件,它也将在父项中关闭。

答案 3 :(得分:0)

我有这个代码,我看到文件描述符与父pid共享

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


pid_t p;

int main(){
    if((p = fork()) != -1){
            open("file",O_APPEND);
            sleep(120);
    }
}

gcc -o fork fork.c

root      4576  2675  0 06:39 ttyS0    00:00:00 ./fork
root      4577  4576  0 06:39 ttyS0    00:00:00 ./fork

lsof -p 4576
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF  NODE NAME
fork    4576 root  cwd    DIR    8,1     4096 69266 /root
fork    4576 root  rtd    DIR    8,1     4096     2 /
fork    4576 root  txt    REG    8,1     9882 70117 /root/fork
fork    4576 root  mem    REG    8,1  1682436 23185 /lib/libc-2.11.3.so
fork    4576 root  mem    REG    8,1   143987 23174 /lib/ld-2.11.3.so
fork    4576 root    0u   CHR   4,64      0t0  3340 /dev/ttyS0
fork    4576 root    1u   CHR   4,64      0t0  3340 /dev/ttyS0
fork    4576 root    2u   CHR   4,64      0t0  3340 /dev/ttyS0
fork    4576 root    3r   REG    8,1        0 75269 /root/file

lsof -p 4577
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF  NODE NAME
fork    4577 root  cwd    DIR    8,1     4096 69266 /root
fork    4577 root  rtd    DIR    8,1     4096     2 /
fork    4577 root  txt    REG    8,1     9882 70117 /root/fork
fork    4577 root  mem    REG    8,1  1682436 23185 /lib/libc-2.11.3.so
fork    4577 root  mem    REG    8,1   143987 23174 /lib/ld-2.11.3.so
fork    4577 root    0u   CHR   4,64      0t0  3340 /dev/ttyS0
fork    4577 root    1u   CHR   4,64      0t0  3340 /dev/ttyS0
fork    4577 root    2u   CHR   4,64      0t0  3340 /dev/ttyS0
fork    4577 root    3r   REG    8,1        0 75269 /root/file

使用此python代码的结果相同:

#!/usr/bin/env python

import os
import time

print os.getpid()

if os.fork() is not None:
  print os.getpid()
  fd = open("/etc/passwd","r")
  time.sleep(120)

现在您可以检查父进程和子进程:

python pyfork.py
25131
25131
25132

lsof -p 25131
......
......
......
python  25131 root    3r   REG    8,8      2080  143680 /etc/passwd

lsof -p 25131
......
......
......
python  25132 root    3r   REG    8,8      2080  143680 /etc/passwd