C中的POSIX信号量用于2个分离的程序(消费者/生产者)

时间:2018-06-14 22:38:00

标签: c multithreading posix semaphore

我试图在C中实现生产者/消费者问题。我知道如何使用" fork"来处理它,但在这种情况下,我将实现两个程序。一个用于生产者,一个用于消费者。 对于生产者:信号量必须初始化并且在循环中(到100),信号量应增加其值并打印出来。这已经很好了。 对于消费者:在生产者中初始化的信号量应打开并在循环中(至10)其值应减少并打印。 当我为消费者运行该过程时:打印内存访问错误。 我完全不知道,我做错了什么。谢谢你的帮助!

消费者:

#include <semaphore.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <fcntl.h> 
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/stat.h>

int main() {
    int value;
    sem_t *mySem = sem_open("sem",  O_CREAT|O_EXCL , S_IRUSR|S_IWUSR , 0); 

    for(int i=0; i < 10; i++) {
        sem_wait(mySem);
        sem_getvalue(mySem, &value); 
        printf("The value of the semaphore is %d\n", value);
    }
    sem_close(mySem);
    sem_unlink("sem");
    return 0;
}

生产者:

#include <semaphore.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>

sem_t sem;

int main() {
    sem_init(&sem, 0, 0);
    int value; 
    for(int i=0; i < 100; i++) {
        sleep(1);
        sem_post(&sem);
        sem_getvalue(&sem, &value); 
        printf("The value of the semaphore is %d\n", value);
    }

    sem_destroy(&sem);
    return 0;
}

2 个答案:

答案 0 :(得分:0)

嗯,你期望sem_init(&sem, 0, 0);做什么? sem与消费者有什么关系?

对于通过任何 n IPC进行通信的两个不相关的进程,他们必须按名称就资源达成一致。如果他们共享文件,则为真。如果他们共享一个信号量也是如此。这就是命名信号量的用途。

我修改了你的程序以使用一个命名的信号量。制作人创造并独家拥有它;消费者如果不存在则会出错。

消费者:

#include <err.h> 
#include <fcntl.h> 
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <sys/ipc.h>
#include <sys/stat.h>
#include <sys/types.h>

static const char name[] = "sem";

int main() {
    int value;

    sem_t *sem = sem_open(name, 0, S_IRUSR|S_IWUSR, 0);
    if( sem == SEM_FAILED ) {
      err(EXIT_FAILURE, "sem_open");
    }

    for(int i=0; i < 10; i++) {
        sem_wait(sem);
        sem_getvalue(sem, &value); 
        printf("The value of the semaphore is %d\n", value);
    }
    if( -1 == sem_close(sem) ) {
      err(EXIT_FAILURE, "sem_close");
    }
    if( -1 == sem_unlink(name) ) {
      err(EXIT_FAILURE, "sem_unlink");
    }

    return 0;
}

制片:

#include <err.h> 
#include <fcntl.h> 
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

static const char name[] = "sem";

int main() {
    sem_unlink(name); // ignore error if not extant
    int value; 

    sem_t *sem = sem_open(name, O_CREAT|O_EXCL, S_IRUSR|S_IWUSR, 0);
    if( sem == SEM_FAILED ) {
      err(EXIT_FAILURE, "sem_open");
    }

    for(int i=0; i < 100; i++) {
        sleep(1);
        sem_post(sem);
        sem_getvalue(sem, &value); 
        printf("The value of the semaphore is %d\n", value);
    }

    sem_destroy(sem);
    return 0;
}

我认为你现在发现它们的效果会更好。不过,我建议你遵循我的主导,并检查每个返回代码,并在出现任何问题时退出。对于像这样的试用代码,这是使其正常运行的最快方法。

答案 1 :(得分:0)

感谢您的纠正。这完全符合我的目的。 使用sem_init我应该用0作为Start-Value来初始化信号量。 似乎错误是在生产者进程中使用它而不是指针和sem_open。 这是我第一次使用命名信号量的经历,因此很难看到我的错误。

非常感谢