Труба не дает один и тот же результат каждый раз в C - PullRequest
0 голосов
/ 14 февраля 2020

Я пытаюсь прочитать файл родительским процессом, отправить содержимое двум дочерним процессам, а дочерние процессы записать содержимое в сегмент общей памяти. Однако при каждом запуске я получаю разные выходные данные и не могу понять, почему.

Я использую два именованных канала, и после записи в общую память родительский процесс открывает общую память и считывает содержимое каждой памяти.

Первый дочерний элемент записывает в память по мере поступления, но второй дочерний элемент преобразуется в шестнадцатеричное.

Вот моя основная функция; предположим, что stringtohex() работает правильно.

int main()
{
    pid_t pid_1, pid_2;

    int fd, sd;     // pipes
    const int SIZE = 4096;
    const char infile[] = "in.txt";

    FILE *tp; // file pointers

    pid_1 = fork();

    if (pid_1 < 0)
    {
        fprintf(stderr, "Fork 1 failed");
        return(1);
    }

    if (pid_1 > 0)
    {
        pid_2 = fork();

        if (pid_2 < 0)
        {
            fprintf(stderr, "Fork 2 failed");
            return(1);
        }

        if (pid_2 > 0) // parent
        {
            tp = fopen(infile, "r");

            if (tp == 0)
            {
                fprintf(stderr, "Failed to open %s for reading", infile);
                return(1);
            }

            mknod(PIPE_NAME_1, S_IFIFO | 0666, 0);
            mknod(PIPE_NAME_2, S_IFIFO | 0666, 0);

            fd = open(PIPE_NAME_1, O_WRONLY);
            sd = open(PIPE_NAME_2, O_WRONLY);

            if (fd > 0 && sd > 0)
            {
                char line[300];

                while (fgets(line, sizeof(line), tp))
                {
                    int len = strlen(line);
                    int num_1 = write(fd, line, len);
                    int num_2 = write(sd, line, len);
                    if (num_1 != len || num_2 != len)
                        perror("write");
                    else
                        printf("Ch 1: wrote %d bytes\n", num_1);
                    printf("Ch 2: wrote %d bytes\n", num_2);
                }
                close(fd);
                close(sd);
            }

            fclose(tp);

            wait(NULL);

            int shm_fd = shm_open("Ch_1", O_RDONLY, 0666);

            if (shm_fd == -1)
            {
                fprintf(stderr, "Failed: Shared Memory 1");
                exit(-1);
            }

            int shm_sd = shm_open("Ch_2", O_RDONLY, 0666);

            if (shm_sd == -1)
            {
                fprintf(stderr, "Failed: Shared Memory 2");
                exit(-1);
            }

            void *ptr = mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);

            if (ptr == MAP_FAILED)
            {
                printf("Map failed 1\n");
                return -1;
            }

            void *ptr2 = mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_sd, 0);

            if (ptr2 == MAP_FAILED)
            {
                printf("Map failed 2\n");
                return -1;
            }

            fprintf(stdout, "Normal input: \n%s\n", ptr);
            fprintf(stderr, "Hexadecimal: \n%s\n", ptr2);
        }
        else // second child
        {
            // open shared memory segment
            int shm_child_2 = shm_open("Ch_2", O_CREAT | O_RDWR, 0666);

            // configure the size of the shared memory segment
            ftruncate(shm_child_2, SIZE);
            // map the pointer to the segment
            void *ptr_child_2 = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_child_2, 0);

            if (ptr_child_2 == MAP_FAILED)
            {
                printf("Map failed 3\n");
                return -1;
            }

            // configure named pipe
            mknod(PIPE_NAME_2, S_IFIFO | 0666, 0);
            sd = open(PIPE_NAME_2, O_RDONLY);

            if (sd > 0) // reading from pipe
            {
                int num;
                char s[300];

                while ((num = read(sd, s, sizeof(s))) > 0)
                {
                    // convert to hexadecimal
                    char hex[strlen(s) * 2 + 1];
                    stringtohex(s, hex);
                    // write into segment
                    sprintf(ptr_child_2, "%s", hex);
                    ptr_child_2 += strlen(s) * 2;
                }
                close(sd);
            }
            exit(0);
        }
    }
    else // first child
    {
        // create shared memory segment
        int shm_child_1 = shm_open("Ch_1", O_CREAT | O_RDWR, 0666);

        // configure the size of the shared memory segment
        ftruncate(shm_child_1, SIZE);
        // map the pointer to the segment
        void *ptr_child_1 = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_child_1, 0);

        if (ptr_child_1 == MAP_FAILED)
        {
            printf("Map failed 4\n");
            return -1;
        }
        // configure named pipe
        mknod(PIPE_NAME_1, S_IFIFO | 0666, 0);
        fd = open(PIPE_NAME_1, O_RDONLY);

        if (fd > 0) // reading from pipe
        {
            int num;
            char s[300];
            while ((num = read(fd, s, strlen(s))) > 0)
            {
                // write into segment
                sprintf(ptr_child_1, "%s", s);
                ptr_child_1 += strlen(s);
            }
            close(fd);
        }
        exit(0);
    }

    return 0;
}

Например, входной файл имеет:

Harun
sasmaz
59900
1234
Aaaa

Результаты:

Обычный ввод: HARUN sasmaz 59900 1234 Aaaa4

шестнадцатеричных: 484152554E0A7361736D617A0A35393930300A313233340A41616161

или

Нормальный вход: HARUN sasmaz asmaz59900 1234

Аааа

Hexadecimal: 484152554E0A7361736D617A0A35393930300A0A313233340A41616161FF03

...