我已经完成了最终计算字代码的写作。它计算文件中的单词总数。 (即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()函数计算文件,直到下一个文件夹。文件数是必要的,因为它是分叉数。
每个文件夹都应该是文件的父文件夹。文件包含在该文件夹中。
代码:
#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;
}
而不是叉子你可以使用线程也轻量和容易,然后这由于管道和所有这些东西.http://stackoverflow.com/questions/5514464/difference-between-pthread-and-fork-on -gnu-linux –
我也会学习它,但现在是学习使用fork()和pipe()的时候了。 @sonukumar – NewCoder
这是一个有趣的问题来学习。然而,调用'fork()'为每个'count()'创建一个进程对于当前的操作系统来说开销太大,并且可能会导致系统崩溃(参见“叉炸弹”)。稍微好一点的方法是为每个目录设置'fork()',但是这有一个类似的开销。一个更好的方法是将多个工作进程fork到系统上,使父进程递归扫描文件系统上的文件并将这些文件路径添加到队列中。每个工人都会通过它自己的'pipe()'与父母沟通。 – OregonTrail