【问题标题】:Strange fork() issue in CC中奇怪的fork()问题
【发布时间】:2016-02-19 16:18:57
【问题描述】:

这是一个基本 mapReduce 的赋值,用于查找文本文件中字符串的出现次数。

我有一个只调用 spawnMapper() 的 main。

问题是 fork() == 0 但它不会进入该部分并打印“我成功了!”或其他任何东西。如果我将 int pid 设置为 fork 返回的内容,或者我直接使用 fork,这是正确的。

请帮忙,它可以编译但无法正常工作,我很困惑。

#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include "reducer.h"

//parent = greater than 1 child = 0

char fpeek(FILE *file);

void spawnMapper(char* keyword, char* fileLocation, int numberMappers){

    FILE *fptr;

    if((fptr=fopen(fileLocation, "r")) == NULL){
        printf("ERROR! opening file");
        exit(1);
    }

    fseek(fptr, 0L, SEEK_END);
    int size = ftell(fptr);

    int mapperSize = size/numberMappers;
    fseek(fptr, 0L, SEEK_SET);

    int i;
    for(i = 0; i < numberMappers; i++){

        fptr = fopen(fileLocation, "r");
        int pToC[2]; //pipe parent to child
        int cToP[2]; //pipe child to parent
        if(pipe(pToC) == -1 || pipe(cToP) == -1){
            printf("pipe failure");
            exit(1);
        }

        if (fork() ==  0) {
            printf("I made it!");
            fptr = fopen(fileLocation,"r");
            int threadSize = 0;
            int found = 0;
            while(fpeek(fptr) != EOF && threadSize < mapperSize){
                fseek(fptr, i*mapperSize, SEEK_SET);
                char* stringCheck;
                fscanf(fptr, "%s", stringCheck);                
                if(strcmp(keyword, stringCheck) == 0){
                    found += 1;
                }
                threadSize += strlen(stringCheck);
            }
            printf("found %d", found);
            //pipes to parent how many found 
        }
        else{

        }
    }
    fclose(fptr);   

}

char fpeek(FILE *stream){
    char c;

    c = fgetc(stream);
    ungetc(c, stream);

    return c;
}

【问题讨论】:

  • printf 字符串的末尾添加一个“\n”。 printf 是行缓冲的 - 在遇到换行符之前它不会刷新到标准输出。初学者的常见陷阱,因为它看起来好像某些代码部分没有执行。
  • 您也可以直接将数据写入标准输出。我认为这是无缓冲的。也许试试char* buf="whatever to show on screen";ssize_t bytesprinted=write(STDOUT,buf,strlen(buf));。唯一的问题是格式化字符不能像在 printf 中那样工作。
  • 你不检查fork()调用是否成功执行。它可能会失败而您没有注意到它,因为它通过else 路径。

标签: c mapreduce operating-system fork


【解决方案1】:

Kaylum 在 cmets 中声明 printf 是行缓冲的。这是一个普遍的误解。 stdin 是行缓冲的;其他功能(例如putchar)也会受到影响。尽管如此,他的解决方案是正确的:打印一个换行符以强制立即打印整行。

或者,fflush(stdout); 将导致立即打印文本不需要换行符。

在我看来,迈克的建议并不奏效,因为根本问题在您的程序运行之前就与termios 相关;终端处于cooked/canonical 模式(意味着termios 将等到换行符再发送所有数据,以便它可以代表应用程序处理诸如退格之类的事情)。如果您想将终端设置为原始模式,这意味着一旦按下键,字符就会被发送到您的程序,这与 C 无关,但您可能需要阅读 this pagethis page...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    • 2012-10-08
    • 2011-05-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多