我有以下代码,我必须输入2个参数作为输入,其中:第一个参数是一个数字。如果此数字是2的倍数,那么将使用fork创建15个子进程。如果该数字是3的倍数,则将创建10个进程。如果该数字是5的倍数,则将创建7个进程。第二个参数是一个文件,其大小(以字节为单位)将被分成创建的进程数,每个子进程将读取文件的一部分,它们将该部分保存到变量中,最后父进程显示所有该变量中的文本。例如,我使用./p 5 /home/directoryFile.c运行该程序。所以我有7个子进程,让我们说文件大小是700字节。这意味着每个子进程应该读取100个字节,它们将它保存到变量(附加内容),最后父进程显示所有内容。问题是应该显示父项中所有内容的变量textToSend没有显示任何内容......我相信孩子中的sprintf行应该有问题。
//gcc Test.c -o p
//./p 5 /home/directoryFile.c
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
int studentId, children = 0, j, i, childNumber[15], fdFile, fdread;
float bytesToRead;
char directory[50];
char *buffer = malloc(256), *textToSend = malloc(256);
system("clear");
if(argc-1 < 1)
{
printf("\nSome arguments are missing\n");
return EXIT_FAILURE;
}
studentId = atoi(argv[1]);
strcpy(directory,argv[2]);
if((studentId%2) == 0)
{
children = 15;
}
else
{
if((studentId%3) == 0)
{
children = 10;
}
else
{
if((studentId%5) == 0)
{
children = 7;
}
else
{
printf("\nStudentId is not multiple of 2, 3 o 5\n");
return EXIT_FAILURE;
}
}
}
struct stat fileInfo;
stat(argv[2],&fileInfo);
bytesToRead = fileInfo.st_size / children;
printf("children: %d\n",children);
printf("File Size: %lld\n",(long long int) fileInfo.st_size);
printf("Bytes: %.2f\n",bytesToRead);
fdFile = open(directory,O_RDONLY);
if(fdFile == -1)
{
printf("\nError opening the fileo\n");
return EXIT_FAILURE;
}
for(i=0;i<children;i++)
{
childNumber[i] = fork();
if(childNumber[i] == -1)
{
printf("\nError creating the child process\n");
return EXIT_FAILURE;
}
if(childNumber[i] == 0)
{
fdread = read(fdFile,buffer,bytesToRead);
if(fdread == -1)
{
printf("\nError reading the file\n");
return EXIT_FAILURE;
}
printf("%s",buffer);
//printf("\n\n------------------------\n\n");
sprintf(textToSend,"%s%s",textToSend,buffer);
return EXIT_SUCCESS;
}
else
{
//waitpid(childNumber[i],NULL,WNOHANG);
}
}
printf("\nThis is the content of the file: %s\n",textToSend);
close(fdFile);
for(j=0;j<children;j++)
{
wait(NULL);
}
return EXIT_SUCCESS;
}
会发生什么?缓冲区正确显示文件的一部分... 它可能是sprintf函数吗?
答案 0 :(得分:1)
您正在使用sprintf
打印到您的进程之间未共享的本地缓冲区。
当您fork
您的孩子收到所有私人父母记忆的完整私人副本时。默认情况下,所有内存都是私有的,除非特别指定为共享内存。
如果您将其分配为共享
char * textToSend = mmap(NULL, 256, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
然后,您可以从所有进程访问相同的内存。
这不会说明您必须告诉所有其他进程缓冲区的启动已移动的事实,因此需要额外的共享变量和同步访问。目前您没有附加sprintf
的文字,您将覆盖之前的任何内容。
最后,如果您希望将来自不同进程的结果汇集在一起,您可能需要使用管道(pipe(2)
)而不是共享内存。