【问题标题】:how to synchronize file reading for reading the same file如何同步文件读取以读取相同的文件
【发布时间】:2023-03-10 06:12:01
【问题描述】:

问题

大家好,我正在尝试让两个进程读取同一个文件。这很容易,但是我需要两个进程以这样的方式读取文件,即它们不会读取相同的数据,也就是当一个进程读取并更改指针的位置时,然后它会更改另一个进程上的指针,直到EOF。我如何做到这一点?

我当前的实现将为每个进程读取文件,但随后会从两个进程的 a-z 读取。

我想要

的输入

acdef

然后给出

的输出

program1 读取:a
程序2读取:b
程序 1 读取:c
程序 2 读取:d
程序 1 读取:e
程序 2 读取:f
找到 EOF,正在退出程序

背景

我正在为此操作系统课程构建的项目的背景。该项目将执行一个名为 program1 的程序,然后该程序将创建 9 个管道,一个信号量,一个共享内存,用于计算已读取的字符数,然后还接受文件名的命令行参数。第一个程序还将在创建其他所有内容后生成 9 个子节点,并将所有以前的信息传递给它们,一个从 program1 到特定子节点的管道、信号量、共享内存位置、文件名。

每个孩子都可以同步访问一个文件,共享内存。然后每个孩子将随机读取 1-10 个字符,然后将共享内存增加该数量。然后,孩子们将发送当前具有访问权限的程序的名称以及已读取的字符并将它们写入管道。如果他们到达行尾,他们还将在写入管道的同一字符串中写入读取的字符总数。当特定的孩子这样做时,它会将执行传递给program1执行。

当程序一通过信号量获得执行权限时,它将读取通过所有非阻塞管道发送的字符串。然后将该字符串写入输出文件,然后释放信号量供任何子级再次使用,直到达到 eof。

程序尝试

这是一个示例程序,显示出了什么问题。我正在尝试将文件名传递给孩子然后父母和孩子都试图同时同步读取文件。

父母

#define  key (3000)

int main() 
{ 


    FILE *fPTR;
    int c, semID;

    struct sembuf operations[1];


    pid_t PID1;

    int argCount = 2;
    int size = 20;

    union semun {


        int value;
        struct semid_ds *buffer;
        ushort *array;

    } arg;


    char **args = (char **) malloc( (argCount) * (sizeof (char *) ));
    args[0] =     (char *)  malloc( (size)     * (sizeof (char  ) ));
    args[1] =     (char *)"inputTest.txt";



    semID = semget(key, 3, 0666 | IPC_CREAT);


    fPTR = fopen("inputTest.txt", "r");


    if(semctl(semID, 0, SETVAL, arg) < 0){


        fprintf(stderr, "was unable to set value of sempahore 0" );
        exit(0);
    }



    PID1 = fork();



    if(PID1 == 0){

        sprintf(args[0], "%d", semID);


        if(execvp("./TestReadingChild", args) == -1){

            printf("failed to execute TestReadingChild\n");
            exit(0);
        }

    }

    if(PID1 >= 0){


        while(1){


            if(semctl(semID, 0, GETVAL, arg) == 0){

                if((c = fgetc(fPTR)) != EOF){

                    printf("Program1 read: %c\n", (char) c);
                }else{

                    fclose(fPTR);
                    break;
                }





                operations[0].sem_num = 0;
                operations[0].sem_op = 1;
                operations[0].sem_flg = 0;

                semop(semID, operations, 1);


            }


        }
    }


}

孩子

#define  key (3000)

int main(int argc, char *argv[]) 
{ 

    char *fileName = argv[1];
    FILE *fPTR;
    int semID = atoi(argv[0]);
    int c;

    struct sembuf operations[1];

    pid_t PID1;

    int argCount = 2;
    int size = 20;

    union semun {


        int value;
        struct semid_ds *buffer;
        ushort *array;

    } arg;

    char **args = (char **) malloc( (argCount) * (sizeof (char *) ));
    args[0] =     (char *)  malloc( (size)     * (sizeof (char  ) ));
    args[1] =     (char *)  fileName;


    semID = semget(key, 3, 0666 | IPC_CREAT);
    fPTR = fopen(fileName, "r");


    while(1){


        if(semctl(semID, 0, GETVAL, arg) == 1){

            if((c = fgetc(fPTR)) != EOF){

                printf("Program2 read: %c\n", (char) c);
            }else{
                fclose(fPTR);
                break;
            }





            operations[0].sem_num = 0;
            operations[0].sem_op = -1;
            operations[0].sem_flg = 0;

            semop(semID, operations, 1);
        }


    }
}

【问题讨论】:

  • 在两个进程之间创建一个共享内存并将文件指针放入其中
  • 要做到这一点,我会接受它,我必须使 mmap 的大小为 sizeof(FILE)?这。每次我最终读取字符时,它都会更新文件指针位置,而不是我想象的。
  • 不!只需将文件指针放在共享内存上,即您需要使用 sizeof(FILE *) 在 shm 中分配内存,这只是一个整数值;但是当两个进程想要访问它时要小心 shm 并发。你可以用信号量做到这一点

标签: c io synchronization


【解决方案1】:

在两个进程之间创建一个共享内存并将文件指针放入其中。

为此,只需将文件指针放在共享内存上,即您需要使用 sizeof(FILE *) 在 shm 中分配内存,这只是一个整数值;但是当两个进程想要访问它时要小心 shm 并发。你可以用信号量来做到这一点。

【讨论】:

  • 太棒了,听起来不错。似乎是解决我的问题的一个非常简单的方法。谢谢。现在我已经知道如何使用共享内存了
  • 好的,那么如何将文件指针分配给内存地址?那个对我来说有点奇怪。
  • @Fel 你应该使用shm api,例如shm_openmmap;见stackoverflow.com/questions/43923518/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-12
相关资源
最近更新 更多