简体   繁体   English

睡觉的理发师 - 共享 memory 队列不起作用?

[英]Sleeping barber - shared memory queue not working?

few days ago I started working on the sleeping barber problem , got some issues with segmentation fault But they have been solved here Even though I fixed the missing parts, I still have a problem.几天前我开始研究睡眠理发师的问题,遇到了一些分段错误的问题, 但是在这里已经解决了即使我修复了缺失的部分,我仍然有问题。 I need to use FIFO queue, and create shared memory for it.我需要使用 FIFO 队列,并为其创建共享 memory。 I get no errors when creating it.创建它时我没有收到任何错误。 Running the client should let me put clientAmount of clients into the queue, from which barber should be getting them.运行客户端应该让我将clientAmount的客户端放入队列中,理发师应该从中获取它们。 Every client is described by his process id.每个客户端都由他的进程 ID 描述。 But when I try to do so, client program shows that clients have been added to queue:但是当我尝试这样做时,客户端程序显示客户端已添加到队列中:

2101 entered the queue
2099 entered the queue
2104 entered the queue
2097 entered the queue
2103 entered the queue
2095 entered the queue
2102 entered the queue
2098 entered the queue
2096 entered the queue

but when I run the barber code, all I get is:但是当我运行理发师代码时,我得到的只是:

Queue empty, I fall asleep
I'm waking up
Queue empty, I fall asleep
I'm waking up
Queue empty, I fall asleep
I'm waking up
Queue empty, I fall asleep
I'm waking up
Queue empty, I fall asleep
I'm waking up
Queue empty, I fall asleep
I'm waking up
Queue empty, I fall asleep
I'm waking up
Queue empty, I fall asleep
I'm waking up

I'm not really sure what to do here.我不确定在这里做什么。

The code for client:客户端代码:

#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "functions.h"
#include <sys/mman.h>
#include <unistd.h>
#include <signal.h>
int numberOfCuts;
int isCut;
int isDone;
void status(int f);
int main(int argc,char* argv[])
{

     if(argc < 3){
        printf("Error while executing program, invalid amount of arguments");
        return 0;
    }
    sem_t *barber;
    sem_t *queue;
    sem_t *client;
    sem_t *pillow;
    int clientsAmount;

    int sharedmem, waitRoomSize;
    struct Queue* waitroom;
    void *space;
    int i;
    signal(SIGUSR1, status);


    clientsAmount = atoi(argv[1]);
    numberOfCuts = atoi(argv[4]);

    barber = sem_open("/B", O_RDWR);
     if((barber == SEM_FAILED)){
        perror("Error while getting semaphore for barber");
        exit(1);
        }

    queue = sem_open("/Q", O_RDWR);
    if((queue  == SEM_FAILED)) {
        perror("Error while creating semaphore for queue");
        exit(1);
      }

    client = sem_open("/C", O_RDWR);
    if(client == SEM_FAILED){
        perror("Error while creating semaphore for pillow");
        exit(0);
      }

    sharedmem = shm_open("QueueMem", O_RDWR, 0666);
   if(sharedmem==-1){
       perror("Error while getting shared memory");
       exit(1);
    }
    space = mmap(NULL, sizeof(waitroom), PROT_READ | PROT_WRITE, MAP_SHARED, sharedmem, 0);
   if((space == MAP_FAILED)){
       perror("Error while mapping memory");
       exit(1);
       }
    waitroom = (struct Queue*) space;


    for(i = 0; i< clientsAmount; i++){
        if(fork() == 0){
            int isCut = 0;

                 int id = getpid();
                 printf("%d entered the queue \n", id);
                    sem_wait(queue);

                    sem_post(queue);
                    if( push(waitroom, id)==-1){
                        printf("Queue is full, leaving...");
                        exit(0);
                    }else {
                    push(waitroom, id);
                    sem_wait(pillow);
                    printf("%d: Barber is sleeping, he needs to wake up", id);
                    int x;
                    sem_getvalue(barber, &x);
                    if(x==0){
                        sem_post(barber);
                        while(x!= 0){
                        sem_post(barber);
                        printf("Barber is waking up to cut %d", id);
                        }
                    }
                    sem_post(pillow);

                    _exit(0);
                    }

                }
            }






sem_close(barber);
    sem_unlink("/B");
    sem_close(queue);
    sem_unlink("/Q");
    sem_close(client);
    sem_unlink("/C");


}

void status(int f){
numberOfCuts--;
printf("Remaining cuts: %d", numberOfCuts);
isCut = 1;
while(!numberOfCuts)
{
    printf("Leaving the barber");
    isDone =1;
}
}

The barber code:理发师代码:

#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "functions.h"
#include <sys/mman.h>
#include <unistd.h>
#include <signal.h>
#define BARBER "Barber"
int main(int argc,char* argv[])
{
    if(argc < 2){
        printf("Error while executing program, invalid amount of arguments");
        return 0;
    }
    sem_t *barber;
    sem_t *queue;

    sem_t *client;
    int seats;
    int sharedmem, waitRoomSize;
    struct Queue* waitroom;


    queue = sem_open("/Q", O_CREAT | O_RDWR, 0666, 1);
     if((queue  == SEM_FAILED)) {
        printf("Error while creating semaphore for queue");
        exit(1);
      }
      barber= sem_open("/B", O_CREAT | O_RDWR, 0666, 1);
     if((barber == SEM_FAILED)){
        printf("Error while creating semaphore for barber");
        exit(1);
        }
     client = sem_open("/C", O_CREAT | O_RDWR, 0666, 0);
      if(client == SEM_FAILED){
        printf("Error while creating semaphore for pillow");
        exit(0);
      }




    seats = atoi(argv[1]);
    void *space;



    sharedmem = shm_open("Queue",O_CREAT | O_RDWR, 0666);
    if(sharedmem==-1){
       printf("Error while getting shared memory");
       exit(1);
    }
    waitRoomSize = ftruncate(sharedmem, sizeof(waitroom));
    if((waitRoomSize ==-1)){
       printf("Error while getting size");
       exit(1);
       }
    space = mmap(NULL, sizeof(struct Queue), PROT_READ | PROT_WRITE, MAP_SHARED, sharedmem, 0);
    if((space == MAP_FAILED)){
       printf("Bład podczas mapowania pamiêci");
       exit(1);
       }
    waitroom = (struct Queue*) space;

    queueinit(waitroom, seats);
    printf("semaphores created\n");




    while(1)
    {

     sem_post(queue);
     int x = isEmpty(waitroom);
     sem_wait(queue);
     if(x==1){
        printf("Queue empty, I fall asleep\n");
        sem_post(barber);
        sem_wait(barber);
        printf("I'm waking up\n");
     } else {
     sem_post(queue);

     int id = get(waitroom);
     sem_wait(queue);

     printf("%d, please sit on the chair\n", id);
     printf("Started cutting hair for %d\n", id);
     sleep(2);
     printf("Cutting done for :%d \n", id);

     kill(id, SIGUSR1);

     }
    }


    sem_close(barber);
    sem_unlink("/B");
    sem_close(queue);
    sem_unlink("/Q");
    sem_close(client);
    sem_unlink("/C");

    printf("senaphores unlinked");
    }

The code for queue:队列代码:

#ifndef FUNCTIONS_H_INCLUDED
#define FUNCTIONS_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "functions.h"
#include <sys/mman.h>
#include <unistd.h>
#include <signal.h>

struct Queue{
    int elems[500];
    int size;
    int queueIn;
    int queueOut;
    int isAsleep;
    int mainPID;
    int countCurrent;
};
void queueinit(struct Queue* q, int size){
    q->size = size;
    q->queueIn = q->queueOut = 0;
    q->isAsleep = 0;
    q->countCurrent = 0;

}

int push(struct Queue* q, int e){
    if(q->queueIn == ((q->queueOut -1 + q->size) % q->size)){
        return -1; //Queue full
    }

    q->elems[q->queueIn] = e;
    q->queueIn = (q->queueIn + 1) % q->size;
    return 0;
}

int get(struct Queue* q){
    int e = q->elems[q->queueOut];
    q->queueOut = (q->queueOut + 1) % q->size;
    return e;
}

int isEmpty(struct Queue* q){
    if(q->queueIn == q->queueOut)
        return 1;
    return 0;
}


void lock(sem_t* sem){
if(sem_wait(sem) == -1){
    printf("Error while lockin semaphore");
    exit(1);
}

}

void free_sem(sem_t* sem){
if(sem_post(sem) == -1){
    printf("Error while releasing semaphore");
    exit(1);
}

}

#endif // FUNCTIONS_H_INCLUDED

Any suggestion would be greatly appreciated任何建议将不胜感激

EDIT As of now, few changed have been added:编辑截至目前,添加了一些更改:

  1. Checking the return value of sem_wait and sem_post检查sem_waitsem_post的返回值
  2. Removed the second call for push(waitroom, id) in client删除了客户端中对push(waitroom, id)的第二次调用
  3. Took care of locking and unlocking semaphores, mainly swapped sem_wait with sem_post and vice versa负责锁定和解锁信号量,主要将sem_waitsem_post交换,反之亦然
  4. Got rid of the pillow semaphore摆脱了枕头信号量

Now the program was working nearly fine, however the client code did not exit after all its children finished their work.现在程序几乎可以正常工作了,但是客户端代码在所有子程序完成工作后并没有退出。 Pressing [ENTER] works.[ENTER]有效。 So I took the given advice and created a new semaphore - p , which I lock instead of using pause() in client code, and I unlock it in signal handler status() .所以我接受了给定的建议并创建了一个新的信号量 - p ,我将其锁定而不是在客户端代码中使用pause() ,并在信号处理程序status()中解锁它。 I also cahnged the value with which barber semaphore was initialized - no more double locking or freeing a semaphore.我还更改了barber信号量的初始化值——不再有双重锁定或释放信号量。 I also tried to use abort() function instead of exit but it didn't work.我也尝试使用abort() function 而不是 exit 但它没有用。

What happens now:现在会发生什么:

  1. Barber code does start but nothing happens.理发代码确实开始了,但没有任何反应。
  2. Client code starts and adds some values to queue, and immediately exits.客户端代码启动并向队列添加一些值,然后立即退出。

The updated code for barber:理发师的更新代码:

#include <stdlib.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "functions.h"
#include <sys/mman.h>
#include <unistd.h>
#include <signal.h>
#define BARBER "Barber"
int main(int argc,char* argv[])
{
    if(argc < 2){
        printf("Error while executing program, invalid amount of arguments");
        return 0;
    }
    sem_t *barber;
    sem_t *queue;
    sem_t *p;
    int seats;
    int sharedmem, waitRoomSize;
    struct Queue* waitroom;


    queue = sem_open("/Q", O_CREAT | O_RDWR, 0666, 1);
     if((queue  == SEM_FAILED)) {
        printf("Error while creating semaphore for queue");
        exit(1);
      }
      barber= sem_open("/B", O_CREAT | O_RDWR, 0666, 0);
     if((barber == SEM_FAILED)){
        printf("Error while creating semaphore for barber");
        exit(1);
        }
    p= sem_open("/P", O_CREAT | O_RDWR, 0666, 0);
     if((p == SEM_FAILED)){
        printf("Error while creating semaphore for barber");
        exit(1);
        }



    seats = atoi(argv[1]);
    void *space;
    sharedmem = shm_open("QueueMem",O_CREAT | O_RDWR, 0666);

    if(sharedmem==-1){
       printf("Error while getting shared memory");
       exit(1);
    }
    waitRoomSize = ftruncate(sharedmem, sizeof(waitroom));
    if((waitRoomSize ==-1)){
       printf("Error while getting size");
       exit(1);
       }
    space = mmap(NULL, sizeof(struct Queue), PROT_READ | PROT_WRITE, MAP_SHARED, sharedmem, 0);
    if((space == MAP_FAILED)){
       printf("Error while mapping memory");
       exit(1);
       }
    waitroom = (struct Queue*) space;

    queueinit(waitroom, seats);





    while(1)
    {

        lock(queue);
        if(isEmpty(waitroom)==1){
                printf("Queue empty, I fall asleep\n");
                waitroom->isAsleep = 1;
                free_sem(queue);
                lock(barber);

                printf("I'm waking up\n");

        } else {
            int id = get(waitroom);
            free_sem(queue);

            printf("%d, please sit on the chair\n", id);
            printf("Started cutting hair for %d\n", id);
            sleep(2);
            printf("Cutting done for :%d \n", id);

            kill(id, SIGUSR1);

     }
    }


    sem_close(barber);
    sem_unlink("/B");
    sem_close(queue);
    sem_unlink("/Q");
    sem_close(p);
    sem_unlink("/P");
    //exit(0);
    //printf("senaphores unlinked");
    }

The updated code for client:客户端的更新代码:

#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "functions.h"
#include <sys/mman.h>
#include <unistd.h>
#include <signal.h>
int numberOfCuts;

#include "functions.h"
int id;
sem_t *barber;
sem_t *queue;
sem_t *p;
int clientsAmount;

int sharedmem, waitRoomSize;
struct Queue* waitroom;
void *space;
void status(int f);
void handler(int f);



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

     if(argc < 3){
        printf("Error while executing program, invalid amount of arguments");
        return 0;
    }

    int i;
    signal(SIGUSR1, status);
    signal(SIGINT, handler);
    int pid = getpid();
    clientsAmount = atoi(argv[1]);
    numberOfCuts = atoi(argv[2]);

    barber = sem_open("/B", O_RDWR);
     if((barber == SEM_FAILED)){
        perror("Error while getting semaphore for barber");
        exit(1);
        }

    queue = sem_open("/Q", O_RDWR);
    if((queue  == SEM_FAILED)) {
        perror("Error while creating semaphore for queue");
        exit(1);
      }
    p = sem_open("/P", O_RDWR);
    if((p  == SEM_FAILED)) {
        perror("Error while creating semaphore for queue");
        exit(1);
      }


    sharedmem = shm_open("QueueMem", O_RDWR, 0666);
   if(sharedmem==-1){
       perror("Error while getting shared memory");
       exit(1);
    }
    space = mmap(NULL, sizeof(waitroom), PROT_READ | PROT_WRITE, MAP_SHARED, sharedmem, 0);
   if((space == MAP_FAILED)){
       perror("Error while mapping memory");
       exit(1);
       }
    waitroom = (struct Queue*) space;


    for(i = 0; i< clientsAmount; i++) {
        if(fork() == 0) {
            id = getpid();
            printf("%d entered the barbershop \n", id);
            while(1) {

                lock(queue);
                if( push(waitroom, id)==-1 ) {
                   free_sem(queue);
                    printf("Queue is full, %d leaving...\n", id);
                    exit(0);
                } else {
                    free_sem(queue);
                    printf("%d has entered the queue \n", id);
                    lock(queue);
                    int x;
                    x = waitroom->isAsleep;
                    if(x==1){
                        printf("%d: Barber is sleeping, he needs to wake up\n", id);
                        waitroom->isAsleep = 0;
                        free_sem(queue);
                        free_sem(barber);
                        printf("Barber is waking up to cut %d\n", id);
                    } else {
                        printf("Barber is cutting someone else, %d waiting for its turn", id);
                        free_sem(queue);

                    }

                }
                lock(p);
            }

            break;
        }
    }


    //exit(0);
    sem_close(barber);
    sem_close(queue);
    sem_close(p);
    munmap(space, waitRoomSize);

    exit(0);

}


void handler(int f) {
    printf("Closing");
    sem_close(barber);
    sem_close(queue);

    munmap(space, waitRoomSize);

    exit(0);
}

void status(int f) {

    numberOfCuts--;
    free_sem(p);
    printf("Remaining cuts for %d: %d\n", id, numberOfCuts);

    if(!numberOfCuts) {

        printf("%d is done cutting \n", id);

        exit(0);
    }

}

There are several mistakes in your program:你的程序有几个错误:

  1. In the client code, you are calling sem_wait(pillow) and sem_post(pillow);在客户端代码中,您正在调用sem_wait(pillow)sem_post(pillow); , although the variable pillow has not been initialized. ,虽然变量pillow还没有被初始化。 This causes undefined behavior.这会导致未定义的行为。 In order to initialize a semaphore, you can use the functions sem_init or sem_open .为了初始化信号量,您可以使用函数sem_initsem_open
  2. In the client code, you release the mutex queue immediately after acquiring it.在客户端代码中,您在获取互斥queue后立即释放它。 Instead, you should only release it when you are finished with the queue operation.相反,您应该仅在完成队列操作后才释放它。
  3. In the client code, you call push(waitroom, id) twice, the second call being immediately after the first call.在客户端代码中,您调用push(waitroom, id)两次,第二次调用紧接在第一次调用之后。 This does not make sense.这根本不符合逻辑。
  4. In the barber's main loop, you are releasing the mutexes queue and barber without acquiring them beforehand, then acquire them afterwards.在理发师的主循环中,您正在释放互斥queuebarber ,而无需事先获取它们,然后再获取它们。 A mutex should normally first be acquired, then released, not the other way around.互斥锁通常应该首先被获取,然后被释放,而不是相反。 Use sem_wait for acquiring the mutex, sem_post for releasing it.使用sem_wait获取互斥锁,使用sem_post释放它。 EDIT: Meanwhile, I believe that you are using the semaphore barber for signalling purposes, not as a mutex.编辑:同时,我相信您将信号量barber器用于信号目的,而不是作为互斥体。 In that case, it is correct to call sem_post without having called sem_wait beforehand.在这种情况下,在没有事先调用sem_wait的情况下调用sem_post是正确的。
  5. You are not checking the return value of sem_wait .您没有检查sem_wait的返回值。 For example, it is possible that the function fails due to being interrupted by a signal handler.例如,function 可能由于被信号处理程序中断而失败。
  6. It is not safe to use the function printf in a signal handler.在信号处理程序中使用 function printf是不安全的。 See this link for more information.有关更多信息,请参阅此链接
  7. You are not waiting for the child processes to finish, before terminating the parent process.在终止父进程之前,您无需等待子进程完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM