2015-04-08 90 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給你認識的底層操作,你不新的語言得到的水平。