简体   繁体   English

信号量实施

[英]semaphore implementation

I am getting error in the following program. 我在以下程序中遇到错误。 I want to demonstrate how two processes can share a variable using semaphore. 我想演示两个进程如何使用信号量共享变量。 Can anyone guide me? 谁能指导我?

I am not able to debug the errors... 我无法调试错误......

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<semaphore.h>
int main()
{
  int pid,mutex=1;
  int semid;               /* semid of semaphore set */
  key_t key = 1234; /* key to pass to semget() */
  int nsems = 1; /* nsems to pass to semget() */
  semid=semget(key,nsems,IPC_CREAT|0666);
  if (semid<0) 
  { 
    perror("Semaphore creation failed ");
  }
  if ((pid = fork()) < 0) 
  {
    perror("fork");
    return 1;
  }
  else if(pid==0)
  {
    sem_wait(&semid);
    printf("IN CHILD PROCESS :\n");
    mutex++; 
    printf("value of shared variable =%d",mutex);
    sem_post(&semid);
    return 0;
  }
  sem_wait(&semid);
  printf("IN PARENT PROCESS :\n");
  mutex--;
  printf("value of shared variable =%d",mutex);
  sem_post(&semid);
  return 0;
} 

Your Fundamentals are wrong, the program won't work, so go through the basics and rewrite the program. 您的基础知识错误,程序将无法运行,因此请完成基础知识并重写程序。

Some of the corrections you must make are: 您必须做出的一些更正是:

1) You must make a variable of semaphore type 1)您必须创建一个信号量类型的变量

sem_t semvar;

2) The functions sem_wait() , sem_post() require the semaphore variable but you are passing the semaphore id, which makes no sense. 2)函数sem_wait()sem_post()需要信号量变量,但是你传递了信号量id,这没有任何意义。

sem_wait(&semvar);
   //your critical section code
sem_post(&semvar);

3) You are passing the semaphore to sem_wait() and sem_post() without initializing it. 3)您正在将信号量传递给sem_wait()sem_post()而不进行初始化。 You must initialize it to 1 (in your case) before using it, or you will have a deadlock. 在使用它之前,必须将其初始化为1(在您的情况下),否则您将遇到死锁。

ret = semctl( semid, 1, SETVAL, sem);
if (ret == 1)
     perror("Semaphore failed to initialize");

Study the semaphore API's from the man page and go through this example . 从手册页学习信号量API并查看此示例

The fundamental issue with your code is that you mix two APIs. 您的代码的基本问题是您混合了两个API。 Unfortunately online resources are not great at pointing this out, but there are two semaphore APIs on UNIX-like systems: 不幸的是,在线资源并没有很好地指出这一点,但在类UNIX系统上有两个信号量API:

  • POSIX IPC API, which is a standard API POSIX IPC API,它是一种标准API
  • System V API, which is coming from the old Unix world, but practically available almost all Unix systems System V API,它来自旧的Unix世界,但实际上几乎可用于所有Unix系统

Looking at the code above you used semget() from the System V API and tried to post through sem_post() which comes from the POSIX API. 查看上面的代码,您使用了System V API中的semget(),并尝试发布来自POSIX API的sem_post()。 It is not possible to mix them. 它们不可能混合使用。

To decide which semaphore API you want you don't have so many great resources. 要确定您想要的信号量API,您没有那么多优秀的资源。 The simple best is the "Unix Network Programming" by Stevens. 最简单的是史蒂文斯的“Unix网络编程”。 The section that you probably interested in is in Vol #2. 您可能感兴趣的部分是Vol#2。

These two APIs are surprisingly different. 这两个API出乎意料地不同。 Both support the textbook style semaphores but there are a few good and bad points in the System V API worth mentioning: 两者都支持教科书风格的信号量,但System V API中有一些好处和坏点值得一提:

  • it builds on semaphore sets, so once you created an object with semget() that is a set of semaphores rather then a single one 它建立在信号量集上,所以一旦用semget()创建了一个对象,它就是一组信号量而不是一个信号量
  • the System V API allows you to do atomic operations on these sets. System V API允许您对这些集进行原子操作。 so you can modify or wait for multiple semaphores in a set 所以你可以修改或等待一组中的多个信号量
  • the SysV API allows you to wait for a semaphore to reach a threshold rather than only being non-zero. SysV API允许您等待信号量达到阈值而不是仅为非零。 waiting for a non-zero threshold is also supported, but my previous sentence implies that 也支持等待非零阈值,但我之前的句子暗示了这一点
  • the semaphore resources are pretty limited on every unixes. 每个unix上的信号量资源非常有限。 you can check these with the 'ipcs' command 你可以用'ipcs'命令检查这些
  • there is an undo feature of the System V semaphores, so you can make sure that abnormal program termination doesn't leave your semaphores in an undesired state System V信号量有一个撤消功能,因此您可以确保异常程序终止不会使您的信号量处于不希望的状态

Vary the consumer-rate and the producer-rate (using sleep), to better understand the operation of code. 改变消费者率和生产率(使用睡眠),以更好地理解代码的操作。 The code below is the consumer-producer simulation (over a max-limit on container). 下面的代码是消费者 - 生产者模拟(超过容器的最大限制)。

Code for your reference: 代码供您参考:

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

sem_t semP, semC;
int stock_count = 0;
const int stock_max_limit=5;

void *producer(void *arg) {
    int i, sum=0;
    for (i = 0; i < 10; i++) {

        while(stock_max_limit == stock_count){
            printf("stock overflow, production on wait..\n");
            sem_wait(&semC);
            printf("production operation continues..\n");
        }

        sleep(1);   //production decided here
        stock_count++;
        printf("P::stock-count : %d\n",stock_count);
        sem_post(&semP);
        printf("P::post signal..\n");
    }
 }

void *consumer(void *arg) {
    int i, sum=0;
    for (i = 0; i < 10; i++) {

        while(0 == stock_count){
            printf("stock empty, consumer on wait..\n");
            sem_wait(&semP);
            printf("consumer operation continues..\n");
        }

        sleep(2);   //consumer rate decided here
        stock_count--;
        printf("C::stock-count : %d\n", stock_count);
        sem_post(&semC);
        printf("C::post signal..\n");
        }
}

int main(void) {

    pthread_t tid0,tid1;
    sem_init(&semP, 0, 0);
    sem_init(&semC, 0, 0);

        pthread_create(&tid0, NULL, consumer, NULL);
        pthread_create(&tid1, NULL, producer, NULL);
        pthread_join(tid0, NULL);
        pthread_join(tid1, NULL);

    sem_destroy(&semC);
    sem_destroy(&semP);

    return 0;
}

Please check this out below sample code for semaphore implementation(Lock and unlock). 请在下面查看信号量实现的示例代码(锁定和解锁)。

    #include<stdio.h>
    #include<stdlib.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include<string.h>
    #include<malloc.h>
    #include <sys/sem.h>
    int main()
    {
            int key,share_id,num;
            char *data;
            int semid;
            struct sembuf sb={0,-1,0};
            key=ftok(".",'a');
            if(key == -1 ) {
                    printf("\n\n Initialization Falied of shared memory \n\n");
                    return 1;
            }
            share_id=shmget(key,1024,IPC_CREAT|0744);
            if(share_id == -1 ) {
                    printf("\n\n Error captured while share memory allocation\n\n");
                    return 1;
            }
            data=(char *)shmat(share_id,(void *)0,0);
            strcpy(data,"Testing string\n");
            if(!fork()) { //Child Porcess
                 sb.sem_op=-1; //Lock
                 semop(share_id,(struct sembuf *)&sb,1);

                 strncat(data,"feeding form child\n",20);

                 sb.sem_op=1;//Unlock
                 semop(share_id,(struct sembuf *)&sb,1);
                 _Exit(0);
            } else {     //Parent Process
              sb.sem_op=-1; //Lock
              semop(share_id,(struct sembuf *)&sb,1);

               strncat(data,"feeding form parent\n",20);

              sb.sem_op=1;//Unlock
              semop(share_id,(struct sembuf *)&sb,1);

            }
            return 0;
    }

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

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