c - fseek() 和 fork() 无法正常工作

标签 c process fork fseek

我在将 fseek() 与 fork() 结合使用时遇到问题(实际上使用 XUbuntu 15.10)。 我必须编写一个程序,从文件(“file1”)中读取一系列数字(在不同的行中),并报告与作为参数传递的特定字符串匹配的行数。
我称之为“nf”的程序必须按如下方式调用(./nf number_of_processes file1 match_string)。
程序应创建 number_of_processes 子进程(使用 fork()),每个子进程应处理文件的一个部分(即,如果 number_of_processes 为 5 并且文件有 15 行,则每个子进程应处理 15/5=3 行文件的内容)。
然后,子进程应将结果报告给父进程,父进程将打印在文件中找到的出现次数。

现在的问题是:我使用 fseek 编写了程序(每个子进程在文件中找到其正确的位置并开始分析它的单个部分的长度),但有时它似乎可以工作,而其他一些它会打印不正确的结果,就像它以错误的方式读取文件一样(多次读取或读取垃圾而不是数字字符串)...
你知道为什么会发生这种情况吗?
预先非常感谢。

这些文件如下:
文件1:

1224332
1224332
4363666
4363666
1224332
5445774
2145515
1224332
2145515
1111111
2145515
9789899
2344444
6520031
4363666

nf.c:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>

#define NBYTES 8

int FileLenght(FILE *fp) {
    int cnt=0;
    char c;

    while((c=getc(fp))!=EOF) {
        if(c=='\n') {
            cnt++;
        }
    }

    rewind(fp);

    return cnt;
}

int main (int argc, char *argv[]) {
    int num,vlen=0,i,j=0,cnt=0;
    pid_t *pid;
    int status,sum=0;
    FILE *fp;
    char string[NBYTES+1];

    if(argc!=4) {
        printf("Error using program.\n");
        exit(EXIT_FAILURE);
    }

    num=atoi(argv[1]);

    fp=fopen(argv[2],"r+");

    if(!fp) {
        fprintf(stderr,"Error opening file.\n");
        exit(EXIT_FAILURE);
    }

    vlen=FileLenght(fp);

    pid=malloc(num*sizeof(pid_t));

    for(i=0;i<num;i++) {
        if(!(pid[i]=fork())) {
            fseek(fp,i*(NBYTES)*(vlen/num),SEEK_SET);
            while(j<vlen/num) {
                fscanf(fp,"%s",string);
                printf("Process %d reading from file: %s\n",getpid(),string);
                if(!strcmp(string,argv[3])) {
                    cnt++;
                }
                j++;
                printf("(%d-%d) %d %s=%s\n",getpid(),getppid(),j,string,argv[3]);
            }
            fclose(fp);
            exit(cnt);
        }
    }

    fseek(fp,vlen*NBYTES,SEEK_SET);

    for(i=0;i<num;i++) {
        waitpid(pid[i],&status,0);
        sum+=WEXITSTATUS(status);
    }

    printf("\nTotal found: %d\n",sum);

    fclose(fp);
    free(pid);

    return 0;
}

输出(正确的计数应该是 4 而不是 5):

$ ./nf 5 file1 1224332
Process 18592 reading from file: 1224332
Process 18593 reading from file: 4363666
(18593-18591) 1 4363666=1224332
Process 18593 reading from file: 4363666
(18593-18591) 2 4363666=1224332
(18592-18591) 1 1224332=1224332
Process 18592 reading from file: 1224332
(18592-18591) 2 1224332=1224332
Process 18594 reading from file: 1224332
Process 18596 reading from file: ���ҿ�
(18594-18591) 1 1224332=1224332
Process 18595 reading from file: 2145515
(18595-18591) 1 2145515=1224332
Process 18595 reading from file: 1224332
(18595-18591) 2 1224332=1224332
(18596-18591) 1 ���ҿ�=1224332
Process 18596 reading from file: ���ҿ�
Process 18594 reading from file: 1224332
(18594-18591) 2 1224332=1224332
(18596-18591) 2 ���ҿ�=1224332

Total found: 5

最佳答案

当文件描述符由于 fork() 的结果而在进程之间共享时,文件描述符的所有属性都在副本之间共享,包括当前偏移量。结果,程序中的所有子进程都试图同时从同一文件描述符中查找和读取数据,从而导致各种意外结果。

要解决此问题,您需要延迟打开文件,直到已经 fork ,或者在 fork 后 dup() 文件描述符,为每个子进程创建一个独立的副本。

关于c - fseek() 和 fork() 无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34930078/

相关文章:

c - 链表的基本问题

c - Raspberry Pi 3 PWM LED 脉冲

c - 在 C 中有多个定界符的 scanf

process - jvisualvm 没有列出某些 Java 进程

c - 我如何创建两个子进程,每个子进程在c中运行不同的程序

c++ - 无法为arm-none-linux-gnueabi-g++编译器找到-lpaho-mqtt3c

c - 将变量参数传递给新创建的进程

c++ - Windows C++ 进程与线程

c - 3个 fork 和6个 pipe

c - Unix Fork 奇怪的行为