我有以下问题。

我有两个与信号灯同步的进程,其想法是:

  • 进程1将一些内容写入txt文件
  • 进程2将一些内容写入txt文件
  • 进程1将一些东西写入测试文件

  • 我已经包含了演示此问题的示例代码:
    // semaphore names
    #define NAME1 "/s1"
    #define NAME2 "/s2"
    
    int main()
    {
        /* semaphores for process synchronization */
        sem_t *sm1;
        sm1 = sem_open( NAME1, O_CREAT, 0666, 0);
    
        sem_t *sm2;
        sm2 = sem_open(NAME2, O_CREAT, 0666, 0);
    
        /* processes*/
        int proc1;
        int proc2;
    
        /* file lock struct */
        struct flock fl = {F_WRLCK, SEEK_SET,   0,      0,     0 };
    
        /* create a text file */
        FILE *fp;
        int fd;
    
        fp = fopen("output.txt", "w"); // create and close the file
        fclose(fp);
    
        if((fd = open("output.txt", O_RDWR)) == -1) { // open the file again to get file descriptor
            perror("open");
            exit(1);
        }
    
        fp = fdopen(fd, "w");
    
        /* first process */
        if ((proc1 = fork()) < 0) {
            perror("fork");
            exit(2);
        }
        else if(proc1 == 0) {
            fl.l_type = F_WRLCK; // set the lock type and pid of the forked process
            fl.l_pid = getpid();
    
            if (fcntl(fd, F_SETLKW, &fl) == -1) { // lock the file before writing to it
                perror("fcntl");
                exit(1);
            }
    
            fprintf(fp, "proc1 - action1\n"); // write to the file
    
            fl.l_type = F_UNLCK;
    
            if (fcntl(fd, F_SETLK, &fl) == -1) {  // unlock the file so other processes can write to it
                perror("fcntl");
                exit(1);
            }
    
            fprintf(stdout, "proc1 - action1\n");
    
            sem_post(sm1); // let the second process run
            sem_wait(sm2); // wait till the second process is done
    
            // write one more thing the same way to the text file after the second process is done
            fl.l_type = F_WRLCK;
            fl.l_pid = getpid();
    
            if (fcntl(fd, F_SETLKW, &fl) == -1) {
                perror("fcntl");
                exit(1);
            }
    
            fprintf(fp, "proc1 - action2\n");
    
            fl.l_type = F_UNLCK;
    
            if (fcntl(fd, F_SETLK, &fl) == -1) {
                perror("fcntl");
                exit(1);
            }
    
            fprintf(stdout, "proc1 - action2\n");
    
            exit(0);
        }
    
        /* second process */
        if ((proc2 = fork()) < 0) {
            perror("fork");
            exit(2);
        }
        else if(proc2 == 0) {
            sem_wait(sm1); // waits for proc1 to perform it's first action
    
            // write something to the text file and let proc1 write it's second action
            fl.l_type = F_WRLCK;
            fl.l_pid = getpid();
    
            if (fcntl(fd, F_SETLKW, &fl) == -1) {
                perror("fcntl");
                exit(1);
            }
    
            fprintf(fp, "proc2 - action1\n");
    
            fl.l_type = F_UNLCK;
    
            if (fcntl(fd, F_SETLK, &fl) == -1) {
                perror("fcntl");
                exit(1);
            }
    
            fprintf(stdout, "proc2 - action1\n");
    
            sem_post(sm2);
    
            exit(0);
        }
    
        // wait for both processes to finish
        waitpid(proc1, NULL, 0);
        waitpid(proc2, NULL, 0);
    
        sem_close(sm1);
        sem_unlink(NAME1);
    
        sem_close(sm2);
        sem_unlink(NAME2);
    
        return 0;
    }
    

    我将fprintf包含在stdout行中,以便您可以看到终端中的输出是正确的:
    -proc1 - action1
    -proc2 - action1
    -proc1 - action2
    

    就像它们正在同步一样。但是,output.txt文件中的输出是这样的:
    -proc2 - action1
    -proc1 - action1
    -proc1 - action2
    

    为什么会这样呢?

    另外,在进程写入文件之前,我总是将其锁定,以便其他进程无法访问它然后再次将其解锁。

    我不确定我是否做对了,因此,我很乐意得到任何建议!

    非常感谢!

    最佳答案

    默认情况下,您已缓冲IO-因此,如果缓冲区的输出小于缓冲区大小,则实际上不会将缓冲区刷新到文件,直到关闭它为止(否则,在缓冲区已满时通常会得到一个缓冲区的值...通常为8kb或者)。还要注意,每个进程都有自己的单独缓冲区。

    要解决此问题,请在打印后以及将fseek()写入SEEK_END之前刷新输出,以确保您位于文件末尾。

    fprintf(fp, "proc1 - action1\n"); // write to the file
    fflush(fp);
    

    顺便说一句,我没有检查您的信号量代码的有效性,只是注意到您缺少此关键信息。但是,通常,如果您使用文件锁定,则信号量是多余的...

    关于c - 向同步进程的文件输出顺序写入错误?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36844262/

    10-09 20:19
    查看更多