【发布时间】:2015-06-13 15:35:52
【问题描述】:
我终于写完了数字代码。它计算文件中的总字数。 (即txt)。现在,我想使用多个 fork() 来访问和读取每个文件。我上周学习了。此外,我使用全局变量来保存计数单词的数量。据我所知,如果我应用 fork(),使用的全局变量被分配为 0。为了避免它,我尝试使用 mmap() 和类似的函数,这很好。但是,我也想使用 pipe() (如果可能的话,fifo() )进行通信(保存数字值)。
我使用 nftw() 函数进入文件夹和文件。我的逻辑在下图中。如何在此代码上使用 fork() 和 pipe() (fifo()) ?由于我缺乏经验,fork() 对我来说真的很复杂。我是使用 pipe() 和 fork() 的新手。根据我的想法,代码的逻辑是如果我可以使用 fork() 和 pipe(),那么每个文件(即 txt)都会有 fork() 并通过使用 fork 访问它们。如果有另一个文件夹并且有文件,则再次从创建的 fork 之一创建 fork() ,然后访问 file.我试着解释一下下面的图。谢谢你。我想学习使用它们。
int countInEveryFolder(const char *dir)
使用 是因为我不知道如何计算文件,直到 nftw() 函数中的下一个文件夹。文件数量是必要的,因为它是 fork 的数量。
每个文件夹都应该是文件的父文件夹。文件包含在文件夹中。
代码:
#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;
}
【问题讨论】:
-
你可以使用重量轻且容易的螺纹代替叉子,因为管道和所有这些东西。stackoverflow.com/questions/5514464/…
-
我也会学习它,但现在是学习使用 fork() 和 pipe() 的时候了。 @sonukumar
-
这是一个有趣的学习问题。然而,调用
fork()为每个count()创建一个进程对于当前的操作系统来说开销太大,并且可能会导致系统崩溃(参见“Fork Bomb”)。更好的方法是为每个目录使用fork(),但这有类似的开销。更好的方法是fork()数量等于系统上 CPU 数量的工作进程,让父进程递归扫描文件系统上的文件,并将这些文件路径添加到队列中。每个工人都会通过自己的pipe()与父母沟通。 -
我知道您这样做是出于学习目的,但作为旁注:
fork()(或线程)不太可能提高性能。如果您的底层文件系统位于 HDD 上,则可能会导致性能下降。 -
@NewCoder pastebin.com/V6dvEFnP 检查它没有管道。Fork 用于每个文件。