C - 创建两个可以生成奇数和偶数的进程

C - create two processes which can generate odd and even integers

我有这个任务,我必须创建两个进程,每个进程必须生成 50 个奇数或偶数整数。

Write a simple sequence-number system through which two processes, P1 and P2, can each obtain 50 unique integers, such that one receives all the odd and the other all the even numbers. Use the fork() call to create P1 and P2. Given a file, F, containing a single number, each process must perform the following steps:

a. Open F.
b. Read the sequence number N from the file.
c. Close F.
d. Output N and the process' PID (either on screen or test file).
e. Increment N by 1
f. Open F.
g. Write N to F.
h. Flush F.
i. Close F

作为我在每个过程中都创建了一个循环并且运行上面提到的步骤。但我不确定这种做法是否正确。我已经向我的助教寻求帮助,他建议也这样做(使用睡眠呼叫并等待有效整数)。但问题是我可以在不使用睡眠调用的情况下获得相同的结果。所以我不确定我是否正确地将逻辑应用于代码。有人可以帮忙吗?

这是我的实现:

void getUniqueNumbers() {

    struct process p1;
    struct process p2;
    int numberFromFile;

    pid_t pid = fork();

    // Process 1
    if (pid == 0) {

        int p1Counter = 0;
        p1.processId = getpid();

        while(p1Counter < numLimit) {
            numberFromFile = getNumberFromFile();
            if (numberFromFile % 2 == 0) { // even
                p1.numbers[p1Counter] = numberFromFile;
                printf("N: %d, PID: %d\n", numberFromFile, p1.processId);
                numberFromFile++;
                writeNumberToFile(numberFromFile);
                p1Counter++;
            }
            else {
                sleep(1);
            }

        }

    }
    // Process 2
    else if (pid > 0 ) {

        int p2Counter = 0;
        p2.processId = getpid();

        while(p2Counter < numLimit) {
            numberFromFile = getNumberFromFile();
            if (numberFromFile % 2 != 0) { // odd
                p2.numbers[p2Counter] = numberFromFile;
                printf("N: %d, PID: %d\n", numberFromFile, p2.processId);
                numberFromFile++;
                writeNumberToFile(numberFromFile);
                p2Counter++;
            }
            else {
                sleep(1);
            }
        }

    }
    else {
        printf("Error: Could not create process\n");
    }

}

Read/Write 函数:

// Returns the number included in user provided file
int getNumberFromFile() {

    FILE *fp = fopen(fileName, "rb");
    int num = 0;

    if (fp != 0) {
        char line[10];
        if (fgets(line, sizeof(line), fp) != 0)
            num = atoi(line);
        fclose(fp);
    }

    return num;

}

// Writes a given number to the user provided file
void writeNumberToFile(int num) {

    FILE *fp = fopen(fileName, "w");

    if (fp != 0) {
        fprintf(fp, "%d", num);
        fclose(fp);
    }

}

代码看起来不错。不过可以简化很多。

void getUniqueNumbers()
{
  struct process p;       // We need only 1 structure
  size_t counter = 0;     // sample counter
  int    oddEven;         // flag if we are parent
  pid_t pid = fork();     // Fork here
  if (-1 == pid)
  {
    abort(); // simply die on error
  }

  oddEven = 0 == pid ? 0 : 1;
  p.processId = getpid(); // We are either child or parent.

  while (counter < numLimit)
  {
    int numberFromFile = getNumberFromFile();
    if ((numberFromFile & 1) == oddEven)
    {
      p.numbers[counter++] = numberFromFile;
      printf("N: %d, PID: %ld\n", numberFromFile, (long)p.processId);
      numberFromFile++;
      writeNumberToFile(numberFromFile);
    }
    sleep(1); // sleep in both cases
    // Extra check for parent: if child has died, we are in infinite
    // loop, so check it here
    if (0 != pid && counter < numLimit)
    {
      int status = 0;
      if (waitpid(pid, &status, WNOHANG) > 0)
      {
        printf("Child exited with 0x%08X status\n", status);
        break;
      }
    }
  }

  // wait till child process terminates
  if (0 != pid)
  {
    int status = 0;
    waitpid(pid, &status, 0);
    printf("Child exited with 0x%08X status\n", status);
  }
}

此外,文件 reading/writing 要么使用文件锁定操作,要么使用原子文件更改。重要的是要防止潜在的错误,例如一个线程正在写入数字 40006,而另一个线程设法读取 400。不过在现实生活中不应该发生。

需要文件锁来防止同时访问相同的内容。可以是独占锁,也可以是共享读独占写。

原子修改是一种能够以原子方式替换文件内容的功能,无论写入数据需要多少次操作。它是保持数据一致的替代方法。