clinuxconcurrencymultiprocess

Why doesn't my multi-process writing program trigger concurrent conflict?


I'm trying to trigger some concurrent conflicts by having several processes writing to the same file, but couldn't:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/wait.h>

void concurrent_write()
{
    int create_fd = open("bar.txt", O_CREAT | O_TRUNC, 0644);
    close(create_fd);
    int repeat = 20;
    int num = 4;

    for (int process = 0; process < num; process++)
    {
        int rc = fork();
        if (rc == 0)
        {
            // child
            int write_fd = open("bar.txt", O_WRONLY | O_APPEND, 0644);
            for (int idx = 0; idx < repeat; idx++)
            {
                sleep(1);
                write(write_fd, "child writing\n", strlen("child writing\n"));
            }
            close(write_fd);

            exit(0);
        }
    }

    for (int process = 0; process < num; process++)
    {
        wait(NULL);
        // wait for all children to exits
    }

    printf("write to `bar.txt`\n%d lines written by %d process\n", repeat * num, num);

    printf("wc:");
    if (fork() == 0)
    {
        // child
        char *args[3];
        args[0] = strdup("wc");
        args[1] = strdup("bar.txt");
        args[2] = NULL;
        execvp(args[0], args);
    }
}

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

    return 0;
}

This program fork #num children and then have all of them write #repeat lines to a file. But every time (however I change #repeat and #num) I got the same result that the length of bar.txt (output file) matched the number of total written lines. Why is there no concurrent conflicts triggered?


Solution

  • Writing to a file can be divided into a two-step process:

    1. Locate where you want to write.
    2. Write data into the file.

    You open a file with flag O_APPEND and it ensures that the two-step process is atomic. So, you can always find the lines of the file as the count you set.