【问题标题】:How to get return value of sem_wait()?如何获取 sem_wait() 的返回值?
【发布时间】:2014-03-12 00:57:19
【问题描述】:

我有一个程序应该让两个进程交替执行某项任务。在子进程第五次执行其任务后,它必须销毁一个信号量,并且父进程应该因此而停止。

一开始这听起来很简单,但我很难捕捉到sem_wait() 函数的返回值。

这是我的文件:

#include "Part2Defs.h"

int main() {

  FILE *fptr = 0;

  sem_t *child  = mmap(0, sizeof(sem_t), PROT_READ|PROT_WRITE,
                       MAP_SHARED|MAP_ANONYMOUS, -1, 0);

  sem_t *parent = mmap(0, sizeof(sem_t), PROT_READ|PROT_WRITE,
                 MAP_SHARED|MAP_ANONYMOUS, -1, 0);

  /* save the number that we'll be writing to the file */
  int number = 1, removed = 0;

  sem_init(child,  1, 1);
  sem_init(parent, 1, 0);


  fptr = fopen(BUFFER, "r+");
  if(fptr == 0) {
    printf("An error occurred while opening the file\n");
  }

  fprintf(fptr, "%d", number);

  fclose(fptr);

  int pID = fork();

  if(pID == 0) {

    /* do this FOREVER. */
    while(1) {

      /* I was hoping to get the return value here */
      if(sem_wait(parent) == 0) {

      /* open the file */
      fptr = fopen(BUFFER, "r+");

      printf("B. The number [] was modified by parent\n");

      fclose(fptr);
      sem_post(child);
      }
      else {
        printf("--parent-- waiting for new number to be READ: Identifier removed");
      }
    } 

    return 0;
  }
  else if(pID > 0) {

    /* make a counter to go from 0 to 5 */
    int i = 0;
    while(1) {

      sem_wait(child);

     if(i++ == 5) {
        /* delete the semaphore */
        sem_destroy(parent);

        printf("Semaphore removed\n");
        break;
      }
       /* open the file */
      fptr = fopen(BUFFER, "r+");

      printf("A. The number [] was modified by child\n");

      fclose(fptr);
      sem_post(parent);
   }

    return 0;
  }
  else {
    printf("There was an error creating the fork.\n");
    exit(1);
  }
}

这是我的输出:

A. The number [] was modified by child
B. The number [] was modified by parent
A. The number [] was modified by child
B. The number [] was modified by parent
A. The number [] was modified by child
B. The number [] was modified by parent
A. The number [] was modified by child
B. The number [] was modified by parent
A. The number [] was modified by child
B. The number [] was modified by parent
Semaphore removed

这几乎正是我所希望的,除了父进程从未以包含错误的消息结束。

顺便说一句:这是作业,但由于我缺乏声誉,据说我不允许在自己的帖子上添加作业标签。

【问题讨论】:

  • 为什么对我的问题投反对票?我无法在任何地方找到这个问题,我认为问这个问题是完全合理的......

标签: c process posix semaphore


【解决方案1】:

http://man7.org/linux/man-pages/man3/sem_destroy.3.html

"销毁其他进程或线程当前所在的信号量 阻塞(在 sem_wait(3) 中)会产生未定义的行为。”

我找到了一种方法,可以使用其中一个信号量作为标志来告诉父母何时完成。

#include "Part2Defs.h"


int main() {

  FILE *fptr = 0;

  sem_t *child  = mmap(0, sizeof(sem_t), PROT_READ|PROT_WRITE,
                       MAP_SHARED|MAP_ANONYMOUS, -1, 0);

  sem_t *parent = mmap(0, sizeof(sem_t), PROT_READ|PROT_WRITE,
                 MAP_SHARED|MAP_ANONYMOUS, -1, 0);

  /* save the number that we'll be writing to the file */
  int number = 1, removed = 0;

  sem_init(child,  1, 0);
  sem_init(parent, 1, 0);


  fptr = fopen(BUFFER, "r+");
  if(fptr == 0) {
    printf("An error occurred while opening the file\n");
  }

  fprintf(fptr, "%d", number);

  fclose(fptr);

  int pID = fork();

  if(pID == 0) {

    /* do this FOREVER. */
    while(1) {
      sem_post(child);
      sem_wait(parent);
      if(!sem_trywait(child))
          break;
      /* open the file */
      fptr = fopen(BUFFER, "r+");

      printf("B. The number [] was modified by parent\n");
      fflush(stdout);

      fclose(fptr);
    }

    sem_destroy(child);
    sem_destroy(parent);

    printf("--parent-- waiting for new number to be READ: Identifier removed");
    return 0;
  }
  else if(pID > 0) {

    /* make a counter to go from 0 to 5 */
    int i = 0;
    while(1) {
      sem_wait(child);

     if(i++ == 5) {
        sem_post(child);
        sem_post(parent);
        //Signal the parent that it's done by adding one to child.

        printf("Semaphore removed\n");
        break;
      }
       /* open the file */
      fptr = fopen(BUFFER, "r+");

      printf("A. The number [] was modified by child\n");
      fflush(stdout);

      fclose(fptr);

      sem_post(parent);
   }

    return 0;
  }
  else {
    printf("There was an error creating the fork.\n");
    exit(1);
  }
}

【讨论】:

  • 我也读过这个,但我也读过这个:publib.boulder.ibm.com/infocenter/iseries/v5r3/… 并据此:“任何已阻止在信号量上调用 sem_wait() 或 sem_wait_np() 的线程将解除阻塞并返回一个[EINVAL] 或 [EDESTROYED] 错误。”这就是我所依赖的
  • @AbeFehr Lol,但显然这没有发生,因为代码没有按预期工作。我想我想出了一个可以做到这一点的东西;它使用从sem_post() 返回的错误来结束程序,尽管我必须稍微更改控制流以使其在正确的位置运行。我也不太确定你是否真的需要两个信号量,似乎一个会做
  • 我只是不能完全得到正确的输出,但是使用 sem_post() 的错误是一个非常好的主意。我真的要考虑一段时间了,这是一个非常令人头疼的问题……我的教授实际上要求我们在这个作业中使用两个信号量,即使这没有必要
  • 知道了!将相应的行更改为sem_init(child, 1, 0); 编辑:实际上,它仍然无法正常工作..
  • 知道了!我使用了一个 sem_trywait() 每次都失败,除非子进程在 post() 发送到父级之前将 post()s 发送到子级,所以它基本上使用信号量之一作为标志。
【解决方案2】:

sem_wait 的返回值仅反映其获取锁的成功/失败。如果你想在进程之间进行通信,你需要另一种机制(例如,共享内存)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多