简体   繁体   English

信号量和标准输出缓冲区

[英]Semaphores and the standard out buffer

I implemented the Reader/Writer problem in C using semaphores ( http://en.wikipedia.org/wiki/Readers%E2%80%93writers_problem ). 我使用信号量( http://en.wikipedia.org/wiki/Readers%E2%80%93writers_problem )在C中实现了Reader / Writer问题。

If I put the respective processes to sleep() for one second, the program acts as expected, however if I let it run without interrupting I get something like this: 如果我将相应的进程置于sleep()一秒钟,程序将按预期运行,但是如果我让它在没有中断的情况下运行,我会得到这样的结果:

writer wrote 5
writer wrote 10
reader reads the data:5
writer wrote 15
reader reads the data:15
reader reads the data:15
Semaphore with value of sid = 11599873 is killed 
Semaphore with value of sid = 11632642 is killed 
Semaphore with value of sid = 11665411 is killed 

or 要么

writer wrote 5
writer wrote 10
writer wrote 15
reader reads the data:5
reader reads the data:15
reader reads the data:15
Semaphore with value of sid = 11599873 is killed 
Semaphore with value of sid = 11632642 is killed 
Semaphore with value of sid = 11665411 is killed 

Is this just because the standard out buffer prints these lines out of order, or is there a race condition in my implementation? 这只是因为标准输出缓冲区不按顺序打印这些行,或者在我的实现中是否存在竞争条件?

Here's the code: 这是代码:

#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdlib.h>

#include "sem.h"


#define N 3
#define BUFSIZE 1  
#define PERMS 0666 //0666 - To grant read and write permissions 

int *buffer;
int mutex,write_allowed,rd_count;    /* semaphore variables
                          * mutex, write_allowed - binary semaphore -- critical section
                          * rd_count - counting semaphore */


void reading()
{
    //perform read
    int g;

    g=*buffer;
    printf("reader reads the data:%d\n",g);
}

int main()
{
    int shmid,no=1,i;
    int pid,n;

    if((shmid=shmget(1000,BUFSIZE,IPC_CREAT| PERMS )) < 0)
    {
        printf("\n unable to create shared memory");
        return;
    }
    if((buffer=(int*)shmat(shmid,(char*)0,0)) == (int*)-1)
    {
        printf("\n Shared memory allocation error\n");
        exit(1);
    }

    // semaphore creation
    if((mutex=semget(IPC_PRIVATE,1,PERMS | IPC_CREAT)) == -1)
    {
        printf("\n can't create mutex semaphore");
        exit(1);
    }

    if((write_allowed=semget(IPC_PRIVATE,1,PERMS | IPC_CREAT)) == -1)
    {
         printf("\n can't create empty semaphore");
         exit(1);
     }

    if((rd_count=semget(IPC_PRIVATE,1,PERMS | IPC_CREAT)) == -1)
    {
        printf("\ncan't create full semaphore");
         exit(1);
    }

    // initialze the semaphore  
    sem_create(mutex,1);
    sem_create(write_allowed,1);
    sem_create(rd_count,0);

    //forking a child 
    if((pid=fork()) < 0)
    {
        printf("\n Error in process creation");
         exit(1);
    }

    // write process
    if(pid > 0)
    {
        for(i=0;i<N;i++)
        {
            P(write_allowed);
            //perform write
            *buffer=*buffer+5;
            printf("write wrote %d\n", *buffer);
            //sleep(1);
            V(write_allowed);
        }
    }

    //read process
    if(pid == 0)
    {
        for(i=0;i<N;i++)
        {
            P(mutex);
            rd_count++;
            if(1 == rd_count)
                P(write_allowed);
            V(mutex);
            reading();
            //sleep(1);
            P(mutex);
            rd_count--;
            if(0==rd_count)
                V(write_allowed);
            V(mutex);   
        }
        shmdt(0);
        shmctl(shmid, IPC_RMID, NULL);
        semkill(mutex);
        semkill(write_allowed);
        semkill(rd_count);
      }


}

The sem.h file: sem.h文件:

/************************************************************************/
/*  Operating Systems - Fall 2006
/*                                  */
/*      Semaphore library : sem.h                   */
/*                                                                      */
/*      Originally developed at KSU by a teaching assistant             */
/*                                  */
/*      Description :  The following library is a collection of         */
/*                     routines for using binary semaphores in C:       */
/*          1. seminit - to initialize a semaphore.         */
/*          2. P - to perform a P(S) (wait) operation.      */
/*                      3. V - to perform a V(S) (signal) operation.    */
/*              4. semkill - to remove a semaphore              */
/*                                  */
/*             These routines call system routines:     */
/*          1. semget - to get a semaphore          */
/*          2. semctl - semaphore control operations    */
/*          3. semop  - semaphore operations        */
/*                                  */
/*             Complete manual entries can be obtained by:      */
/*          man semctl | col -b | lpr           */
/************************************************************************/

#include <stdio.h>
#include <sys/types.h> 
#include <sys/ipc.h>
#include <sys/sem.h> 

union arg{          /* This structure is used to call semctl */
    int val;        
    struct semid_ds *buf;
    char *array;
};

/*
 * Create semaphore based on "key" parameter to "initval"
 */


void sem_create(int semid, int initval)
{
 int semval;
union semun
{
 int val;
 struct semid_ds *buf;
 unsigned short *array;
}s;

s.val=initval;
if((semval=semctl(semid,0,SETVAL,s))<0)
  printf("\n Erroe in executing semctl");
}

/*
 * Remove semaphore with semaphore id (sid) from the kernel
 */
static void semkill (sid)
int sid;
{
    if (semctl(sid,0,IPC_RMID,0) == -1)
    perror("semctl (kill)");
    printf("Semaphore with value of sid = %d is killed \n",sid);
}

/*
 * Perform the designated "op" operation on the semaphore. If "op" is -1,
 * then this implements the "P" operation; it decrements the value of the
 * semaphore (semval) if it was >0, 
 * and blocks the caller if it was zero (semval==0)
 * If "op" is 1, then this is simply added to current value of 
 * the semaphore ("V" operation).
 */
static void semcall(sid, op)
int sid;
int op;
{
    struct sembuf sb;

    sb.sem_num = 0; /* semaphore number within sid */
    sb.sem_op = op;
    sb.sem_flg = 0; /* blocking call */
    if (semop(sid, &sb, 1) == -1)
    perror("semop");
}

/*
 * P operation on semaphore "sid". Should be called upon entry to critical
 * region.
 */
static void P(sid)
int sid;
{
    semcall(sid, -1);
}

/*
 * V operation on semaphore "sid". Should be called upon exit from critical
 * region.
 */
static void V(sid)
int sid;
{
    semcall(sid, 1);
}

You don't increment a semaphore by rd_count++; 你不用rd_count++;增加信号量rd_count++; . rd_count is supposedly just a semaphore ID. rd_count应该只是一个信号量ID。 You need to use some kind of function that operates using the semaphore ID to change the state of the semaphore, which is kept somewhere outside your two processes. 您需要使用某种使用信号量ID操作的函数来更改信号量的状态,该信号量保存在两个进程之外的某个位置。

Also I am not familiar with sem_create() , but unless it is a C++ function taking a reference argument, I have my doubts it has any side-effect on the variables you pass it. 我也不熟悉sem_create() ,但除非它是一个带参考参数的C ++函数,否则我怀疑它对你传递的变量有任何副作用。

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

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