乐趣区

关于前端:多进程双buffer读取并处理

题目要求

编写 Linux 平台下的两个 C 语言程序实现如下性能:
(1)X、Y 两个过程相互配合实现对输出文件中数据的解决,并将处理结果写入输入文件。
(2)X 过程负责读分块取输出文件,并将输出数据利用共享内存传输给 Y 过程。
(3)Y 过程负责将读入的数据(假设皆为文本数据)全副解决成大写,而后写入输入文件。
(4)为进步并行效率,X、Y 两个过程之间创立 2 个共享内存区 A、B。X 读入数据到 A 区,而后用 Linux 的信号或信号量机制告诉 Y 过程进行解决;在 Y 解决 A 区数据时,X 持续读入数据到 B 区;B 区数据被填满之后,X 过程告诉 Y 过程解决,本人再持续向 A 区读入数据。如此循环直至全副数据处理结束。

解题

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include <semaphore.h>
#include <sys/ipc.h>
#include <sys/shm.h>

const int BUFFER_SIZE = 2048;

int main(int argc, char const *argv[])
{argv[1];
    // 文件
    int inputFile, outputFile;
    inputFile = open(argv[1], O_RDONLY);
    if(inputFile <= 0){printf("no file %s \n", argv[1]);
        return 0;
    }
    outputFile = open("./output.txt", O_WRONLY | O_CREAT, 0666);

    // 信号量
    sem_t *sem1;
    sem_t *sem2;
    sem1 = sem_open("sem1", O_CREAT, 0666, 1);
    sem2 = sem_open("sem2", O_CREAT, 0666, 0);

    // 共享内存
    // 定义替换空间结构体
    struct switchBuffer
    {char buffer[BUFFER_SIZE];
        int flag;
    };
    struct switchBuffer *buffera; // 替换空间 a,b
    struct switchBuffer *bufferb;
    int shmaId, shmbId;

    // 创立共享内存
    shmaId = shmget((key_t)11, sizeof(buffera), 0666 | IPC_CREAT);
    shmbId = shmget((key_t)22, sizeof(bufferb), 0666 | IPC_CREAT);

    // 主过程读取数据
    // 子过程解决后写入数据
    pid_t cpid;
    cpid = fork();
    if (cpid < 0)
    {printf("error in fork\n");
    }
    else if (cpid == 0)
    {
        // 子过程
        printf("child process pid: %d \t", getpid());

        // 共享内存映射到过程空间
        buffera = (struct switchBuffer *)shmat(shmaId, 0, 0);
        bufferb = (struct switchBuffer *)shmat(shmbId, 0, 0);
        int switchFlag = 1;
        while(1)
        {sem_wait(sem2);
            if (switchFlag)
            {for (int i = 0; i < buffera->flag; ++i)
                {buffera->buffer[i] = toupper(buffera->buffer[i]);
                }
                write(outputFile, buffera->buffer, buffera->flag);
            }
            else
            {for (int i = 0; i < bufferb->flag; ++i)
                {bufferb->buffer[i] = toupper(bufferb->buffer[i]);
                }
                write(outputFile, bufferb->buffer, bufferb->flag);
            }
            switchFlag = !switchFlag;
            sem_post(sem1);
        }
    }
    else
    {
        // 主过程
        // 共享内存映射到过程空间
        buffera = (struct switchBuffer *)shmat(shmaId, 0, 0);
        bufferb = (struct switchBuffer *)shmat(shmbId, 0, 0);

        int fileFlag = 0;
        int switchFlag = 1;

        // 1. 读取文件 ->buffer a
        // 2. 期待解决过程
        // 3. 触发解决过程
        // 4. 读取文件 ->buffer b
        // 5. 期待解决过程
        // 6. 触发解决过程

        // 开始时事后触发 2, 开始运行工作
        // 通过 read 文件为 0 判断终止条件
        // 终止后再次期待解决线程解决最初的一个 buffer
        while (1)
        {if (switchFlag)
            {fileFlag = read(inputFile, buffera->buffer, BUFFER_SIZE);
                buffera->flag = fileFlag;
            }
            else
            {fileFlag = read(inputFile, bufferb->buffer, BUFFER_SIZE);
                bufferb->flag = fileFlag;
            }
            switchFlag = !switchFlag;
            if (fileFlag <= 0)
                break;
            sem_wait(sem1);
            sem_post(sem2);
        }
        sem_wait(sem1);
    }

    // destory
    close(inputFile);
    close(outputFile);
    sem_close(sem1);
    sem_close(sem2);
    sem_unlink("sem1");
    sem_unlink("sem2");
    shmdt(buffera);
    shmdt(bufferb);
    shmctl(shmaId, IPC_RMID, 0);
    shmctl(shmbId, IPC_RMID, 0);
    printf("over\n");
    return 0;
}
退出移动版