c - fork 进程,读取文件但不显示其内容

标签 c linux file buffer fork

我有以下代码,其中我必须输入 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函数?

最佳答案

您正在使用 sprintf 打印到您的进程之间不共享的本地缓冲区。

当您fork 时,您的 child 会收到所有 parent 内存的完整私有(private)副本,该副本是私有(private)的。默认情况下,所有内存都是私有(private)的,除非专门分配为共享内存。

如果分配为共享

 char * textToSend = mmap(NULL, 256, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);

然后您将拥有可从所有进程访问的相同内存。

这不会说明您必须告诉所有其他进程缓冲区的起点已移动,因此这将需要额外的共享变量和同步访问。目前您没有使用 sprintf 附加文本,您正在覆盖任何以前的内容。

最后,如果您希望将来自不同进程的结果汇集在一起​​,您可能希望使用管道 (pipe(2)) 而不是共享内存。

关于c - fork 进程,读取文件但不显示其内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19227708/

相关文章:

c - 在 C 中求矩阵的行列式

c - 如何对在 Windows 中复制文件的最快方法进行基准测试(内存映射与文件 I/O)

linux - 如何模拟管道故障?

c++ - 获取/dev/video0的硬件信息

java - 通过 JNI 读取文件时崩溃,但仅运行代码的 C 元素时成功

java - 创建相关 java.io.File 的安全方法

c - 如何将 SSE 应用于长度不能保证为 4 的倍数的数组?

c - 算法挑战 : Generate Continued Fractions for a float

linux - 依次运行多个bash脚本

java - 如何制作一个接受文件名并可以打印其内容的类?