2015-04-08 79 views
3

我已经完成了最终计算字代码的写作。它计算文件中的单词总数。 (即txt)。现在,我想使用多个fork()来访问和读取每个文件。我在上周学习了。此外,我使用全局变量来保存计数字的数量。据我所知,如果我应用fork(),则将全局变量赋值为0.为了避免它,我尝试使用mmap()和类似的函数okey。但是,我也想使用pipe()(如果可能的话,也使用fifo())进行通信(保存数字值)。在计数字代码上应用fork()和pipe()(或fifo())代码

我使用nftw()函数进入文件夹和文件。我的逻辑在下面的图片上。这个代码如何使用fork()和pipe()(fifo())? fork()对我来说真的很复杂,因为我缺乏经验。我是新的使用pipe()和fork()。根据我的想法,该代码的逻辑是,如果我可以使用fork()和pipe(),则fork()将包含每个文件(即.txt)并使用fork访问它们。如果有另一个文件夹并且存在文件,则再次从创建的分叉创建fork(),然后访问文件。我试图解释下面的图。谢谢。我想学习使用它们。

int countInEveryFolder(const char *dir) 

使用,因为我不知道如何在nftw()函数计算文件,直到下一个文件夹。文件数是必要的,因为它是分叉数。

每个文件夹都应该是文件的父文件夹。文件包含在该文件夹中。

fork scheme

代码:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <sys/wait.h> 
#include <dirent.h> 
#include <errno.h> 
#include <ftw.h> 
#include <ctype.h> 
#include <sys/mman.h> 
#include <locale.h> 
#include <errno.h> 



#define MAX_PATH_LEN  2048 

unsigned long total_words = 0UL; 
unsigned long total_dirs = 0UL; 
unsigned long total_files = 0UL; 


// Just proves counting number of file in a folder 
int countInEveryFolder(const char *dir) { 
    struct stat stDirInfo; 
    struct dirent * stFiles; 
    DIR * stDirIn; 
    char szFullName[MAX_PATH_LEN]; 
    char szDirectory[MAX_PATH_LEN]; 
    struct stat stFileInfo; 

    int numOfFile = 0; 

     strncpy(szDirectory, dir, MAX_PATH_LEN - 1); 


    if (lstat(szDirectory, &stDirInfo) < 0) 
    { 
     perror (szDirectory); 
     return 0; 
    } 
    if (!S_ISDIR(stDirInfo.st_mode)) 
     return 0; 
    if ((stDirIn = opendir(szDirectory)) == NULL) 
    { 
     perror(szDirectory); 
     return 0; 
    } 
    while ((stFiles = readdir(stDirIn)) != NULL) 
    { 
     if (!strcmp(stFiles->d_name, ".") || !strcmp(stFiles->d_name, "..")) 
      continue; 
     sprintf(szFullName, "%s/%s", szDirectory, stFiles -> d_name); 

     if (lstat(szFullName, &stFileInfo) < 0) 
      perror (szFullName); 

     /* is the file a directory? */ 
     if (S_ISREG(stFileInfo.st_mode)) 
     { 
      printf("Filename: %s\n", szFullName); 
      numOfFile++; 
     } 

    } // end while 
    closedir(stDirIn); 
    return numOfFile; 
} 




// Count words in files. 
unsigned long count_words_in_file(const char *const filename) 
{ 
    unsigned long count = 0UL; 
    int errnum = 0; 
    int c; 
    FILE *in; 

    in = fopen(filename, "rt"); 
    if (in == NULL) { 
     errnum = errno; 
     fprintf(stderr, "%s: %s.\n", filename, strerror(errnum)); 
     errno = errnum; 
     return 0UL; 
    } 

    /* Skip leading whitespace. */ 
    do { 
     c = getc(in); 
    } while (isspace(c)); 

    /* Token loop. */ 
    while (c != EOF) { 

     /* This token is a word, if it starts with a letter. */ 
     if (isalpha(c)) 
      count++; 

     /* Skip the rest of this token. */ 
     while (!isspace(c) && c != EOF) 
      c = getc(in); 

     /* Skip the trailing whitespace. */ 
     while (isspace(c)) 
      c = getc(in); 
    } 

    /* Paranoid checking for I/O errors. */ 
    if (!feof(in) || ferror(in)) { 
     fclose(in); 
     fprintf(stderr, "Warning: %s: %s.\n", filename, strerror(EIO)); 
     errnum = EIO; 
    } else 
     if (fclose(in)) { 
      fprintf(stderr, "Warning: %s: %s.\n", filename, strerror(EIO)); 
      errnum = EIO; 
     } 
    errno = errnum; 

    return count; 
} 


// Recursively go in folders 
int nftw_callback(const char *filepath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) 
{ 

    // Directory 
    if (typeflag == FTW_DP || typeflag == FTW_D) 
    { 

     total_dirs++; 
     printf("%*s%s\n", ftwbuf->level * 4, "", filepath); 
     //countInEveryFolder(filepath); 

    } 
    // Folder 
    else if (typeflag == FTW_F) 
    { 
     total_files++; 
     total_words += count_words_in_file(filepath); 
     printf("%*s%s\n", ftwbuf->level * 4, "", filepath); 
    } 
    return 0; 
} 

/* Error message */ 
void err_sys(const char *msg) 
{ 
    perror(msg); 
    fflush(stdout); 
    exit(EXIT_FAILURE); 
} 



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


    total_files = total_dirs = total_words = 0UL; 
    if (nftw(argv[1], nftw_callback, 15, FTW_PHYS) == 0) { 
     /* Success! */ 
     printf("%s: %lu files, %lu directories, %lu words total.\n", 
       argv[1], total_files, total_dirs, total_words); 

    } else { 
     /* Failed... */ 
     err_sys("ntfw"); 
    } 
    putchar('\n'); 



    //printf("\nTotal words = %d\n\n", *wordCount); 
    //printf("\nTotal folders = %d\n\n", *folderCount); 
    //printf("\nTotal childs = %d\n\n", *childCount);  //fork() 


    return 0; 
} 
+0

而不是叉子你可以使用线程也轻量和容易,然后这由于管道和所有这些东西.http://stackoverflow.com/questions/5514464/difference-between-pthread-and-fork-on -gnu-linux –

+0

我也会学习它,但现在是学习使用fork()和pipe()的时候了。 @sonukumar – NewCoder

+0

这是一个有趣的问题来学习。然而,调用'fork()'为每个'count()'创建一个进程对于当前的操作系统来说开销太大,并且可能会导致系统崩溃(参见“叉炸弹”)。稍微好一点的方法是为每个目录设置'fork()',但是这有一个类似的开销。一个更好的方法是将多个工作进程fork到系统上,使父进程递归扫描文件系统上的文件并将这些文件路径添加到队列中。每个工人都会通过它自己的'pipe()'与父母沟通。 – OregonTrail

回答

0

要开始我会写程序有两个阶段。所有文件路径排队(进入链表或出列)的单进程阶段,以及工作进程通过他们的pipe()接收工作并通过计数返回主进程的多进程阶段他们的pipe()。主要过程将使用select()来复用其子项的输入。

一旦您了解如何使用select()pipe() s,那么您就有必要让文件路径发现是并发的。

这样的设计会更容易在Go实现,node.js,或greenlet与Python,但学习如何做到这一点的C给你认识的底层操作,你不新的语言得到的水平。