繁体   English   中英

使用 C 中的 fork 和 pipe 函数计算多进程文件中的行、字符和单词

[英]Using fork and pipe functions in C to count lines, characters, and words from file with multiple processes

我正在尝试使用具有 fork 和 pipe 函数的多个进程来修改读取文件并返回行、单词和字符总数的程序。 程序编译并运行良好,但目前只有当用户输入 1 作为子进程数时,输出才正确。 对于每隔一个正整数,程序返回乘以进程数的正确值。 (例如:如果文件中的行数为 4 并且用户为进程数输入 2,则返回值是 8)有谁知道我如何解决这个问题,以便每个进程划分读取文件的工作而不是每次读取通过整个事情? 用户在运行程序时输入文件名和他们想要的子进程数。 我现在不在乎效率,只关心输出是否正确。 这是我的代码:

//wc.h
#ifndef WC_H
#define WC_H

#include <stdio.h>

typedef struct count_t {
        int linecount;
        int wordcount;
        int charcount;
} count_t;

count_t word_count(FILE* fp, long offset, long size);
extern int crashRate;

#endif



//wc_mul.c
#include "wc.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>

#define MAX_PROC 100
#define MAX_FORK 100

int crashRate = 0;

count_t word_count(FILE* fp, long offset, long size)
{
        char ch;
        long rbytes = 0;

        count_t count;
        // Initialize counter variables
        count.linecount = 0;
        count.wordcount = 0;
        count.charcount = 0;
        
        printf("[pid %d] reading %ld bytes from offset %ld\n", getpid(), size, offset);

        if(fseek(fp, offset, SEEK_SET) < 0) {
                printf("[pid %d] fseek error!\n", getpid());
        }

        while ((ch=getc(fp)) != EOF && rbytes < size) {
                // Increment character count if NOT new line or space
                if (ch != ' ' && ch != '\n') { ++count.charcount; }

                // Increment word count if new line or space character
                if (ch == ' ' || ch == '\n') { ++count.wordcount; }

                // Increment line count if new line character
                if (ch == '\n') { ++count.linecount; }
                rbytes++;
        }

        srand(getpid());
        if(crashRate > 0 && (rand()%100 < crashRate)) 
        {
                printf("[pid %d] crashed.\n", getpid());
                abort();
        }

        return count;
}


int main(int argc, char **argv)
{
                long fsize;
                FILE *fp;
                int numJobs;
        //plist_t plist[MAX_PROC];
                count_t total, count, buf;
                int i, j, pid, status, p[2];
                int nFork = 0;

        if(argc < 3) {
                printf("usage: wc <# of processes> <filname>\n");
                return 0;
        }
        
        if(argc > 3) {
                crashRate = atoi(argv[3]);
                if(crashRate < 0) crashRate = 0;
                if(crashRate > 50) crashRate = 50;
        }
        printf("crashRate RATE: %d\n", crashRate);


        numJobs = atoi(argv[1]);
        if(numJobs > MAX_PROC) numJobs = MAX_PROC;

        total.linecount = 0;
        total.wordcount = 0;
        total.charcount = 0;

        // Open file in read-only mode
        fp = fopen(argv[2], "r");

        if(fp == NULL) {
                printf("File open error: %s\n", argv[2]);
                printf("usage: wc <# of processes> <filname>\n");
                return 0;
        }

        fseek(fp, 0L, SEEK_END);
        fsize = ftell(fp);
        
        fclose(fp);
        // calculate file offset and size to read for each child
        
        for(i = 0; i < numJobs; i++) {
                if(nFork++ > MAX_FORK) return 0;
                if (pipe(p) != 0)
                  exit(1);
                pid = fork();
                if(pid < 0) {
                        printf("Fork failed.\n");
                } else if(pid == 0) {
                        // Child
                        fp = fopen(argv[2], "r");           
                        count = word_count(fp, 0, fsize);
                        write(p[1], &count, sizeof(count));
                        close(p[0]);
                        close(p[1]);
                        // send the result to the parent through the message queue
                        fclose(fp);
                        return 0;
                }
        }
        waitpid(pid, &status, 0);
        close(p[1]);
        for (j=0; j < numJobs; j++) {
          read(p[0], &buf, sizeof(count));
          total.linecount += buf.linecount;
          total.wordcount += buf.wordcount;
          total.charcount += buf.charcount;
        }
        // Parent
        // wait for all children
        // check their exit status
        // read the result from normalliy terminated child
        // re-crete new child if there is one or more failed child
        
        printf("\n========== Final Results ================\n");
        printf("Total Lines : %d \n", total.linecount);
        printf("Total Words : %d \n", total.wordcount);
        printf("Total Characters : %d \n", total.charcount);
        printf("=========================================\n");
        return(0);
}
  1. 你叉之前必须打开pipe 否则它在父级中不可用。

  2. 指针传递给count ,而不是count本身,以readwrite

write(p[1], &count, sizeof(count)); .. read(p[0], &buf, sizeof(count));

  1. 每个孩子都需要在通过close(p[1]) writeclose(p[1])管道的写入端。 现在,您只是关闭了读取端。

PS:并添加通常的结果检查readwrite将是可取的了。


如果您对多个进程使用单个pipe ,一旦第一个孩子关闭pipe ,它就会关闭并且无法再读取。

您需要一组管道,每个进程一个:

int p[numJobs][2];

下面的代码对我有用。 我添加了一些printf以便更好地理解。

int main(int argc, char **argv)
{
    long fsize;
    FILE *fp;
    int numJobs;

    count_t total, count, buf;
    int i, j, pid, status;

    if(argc < 3) {
            printf("usage: wc <# of processes> <filname>\n");
            return 0;
    }
        
    if(argc > 3) {
            crashRate = atoi(argv[3]);
            if(crashRate < 0) crashRate = 0;
            if(crashRate > 50) crashRate = 50;
    }
    printf("crashRate RATE: %d\n", crashRate);


    numJobs = atoi(argv[1]);
    if(numJobs > MAX_PROC) numJobs = MAX_PROC;

    int p[numJobs][2];
    
    total.linecount = 0;
    total.wordcount = 0;
    total.charcount = 0;

    // Open file in read-only mode
    fp = fopen(argv[2], "r");

    if(fp == NULL) {
            printf("File open error: %s\n", argv[2]);
            printf("usage: wc <# of processes> <filname>\n");
            return 0;
    }

    fseek(fp, 0L, SEEK_END);
    fsize = ftell(fp);
    
    fclose(fp);
        // calculate file offset and size to read for each child
        
    for(i = 0; i < numJobs; i++) {
        
        if (pipe(p[i]) != 0) exit(1);

        pid = fork();
        
        if(pid < 0) {
            printf("Fork failed.\n");
            exit(1);
        } else if(pid == 0) {
            
            // Child
            fp = fopen(argv[2], "r");
            count = word_count(fp, 0, fsize);
            fclose(fp);

            close(p[i][0]);

            // send the result to the parent through the message queue
            long bytes_sent;
            
            if ( (bytes_sent = write(p[i][1], &count, sizeof(count)) ) ==-1) {
                printf("Writing into pipe failed.\n");
                exit(1);
            };
            printf("Child  process %d sent %ld bytes (%'d lines, %'d words, %'d chars) \n",getpid(), bytes_sent, count.linecount, count.wordcount, count.charcount);
            
            close(p[i][1]);
            _exit(0);
            
        }
    }
    
    
    // wait for all child processes to close
    while(wait(NULL) != -1){};

    long bytes_read;
    
    for (j=0; j < numJobs; j++) {
                
        if ((bytes_read = read(p[j][0], &buf, sizeof(buf)) ) ==-1) {
            printf("Reading from pipe failed.\n");
            exit(1);
        };

        if (bytes_read){
            
            printf("Parent process %d read %ld bytes (%'d lines, %'d words, %'d chars) \n",getpid(), bytes_read, buf.linecount, buf.wordcount, buf.charcount);

            total.linecount += buf.linecount;
            total.wordcount += buf.wordcount;
            total.charcount += buf.charcount;
        }
                    
        close(p[j][0]);
        close(p[j][1]);
    }


    // Parent
        // wait for all children
        // check their exit status
        // read the result from normalliy terminated child
        // re-create new child if there is one or more failed child
        
        printf("\n========== Final Results ================\n");
        printf("Total Lines : %d \n", total.linecount);
        printf("Total Words : %d \n", total.wordcount);
        printf("Total Characters : %d \n", total.charcount);
        printf("=========================================\n");
        return(0);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM