C语言 信号量实现
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15182328/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
semaphore implementation
提问by chinu
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;
}
回答by Barath Ravikumar
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. You must initialize it to 1 (in your case) before using it, or you will have a deadlock.
3)您将信号量传递给sem_wait()并且sem_post()没有初始化它。您必须在使用之前将其初始化为 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 并完成此示例。
回答by David Beck
The fundamental issue with your code is that you mix two APIs. Unfortunately online resources are not great at pointing this out, but there are two semaphore APIs on UNIX-like systems:
您的代码的根本问题是您混合了两个 API。不幸的是,在线资源并不能很好地指出这一点,但在类 UNIX 系统上有两个信号量 API:
- POSIX IPC API, which is a standard API
- System V API, which is coming from the old Unix world, but practically available almost all Unix systems
- POSIX IPC API,这是一个标准的 API
- 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. It is not possible to mix them.
查看上面的代码,您使用了 System V API 中的 semget() 并尝试通过来自 POSIX API 的 sem_post() 进行发布。混合它们是不可能的。
To decide which semaphore API you want you don't have so many great resources. The simple best is the "Unix Network Programming" by Stevens. The section that you probably interested in is in Vol #2.
要决定您想要哪个信号量 API,您没有那么多好的资源。最简单的最好是史蒂文斯的“Unix 网络编程”。您可能感兴趣的部分在第 2 卷中。
These two APIs are surprisingly different. Both support the textbook style semaphores but there are a few good and bad points in the System V API worth mentioning:
这两个 API 惊人地不同。两者都支持教科书式的信号量,但 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
- the System V API allows you to do atomic operations on these sets. 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. waiting for a non-zero threshold is also supported, but my previous sentence implies that
- the semaphore resources are pretty limited on every unixes. you can check these with the 'ipcs' command
- 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
- 它建立在信号量集上,所以一旦你用 semget() 创建了一个对象,它是一组信号量而不是单个信号量
- System V API 允许您对这些集合进行原子操作。所以你可以修改或等待一组中的多个信号量
- SysV API 允许您等待信号量达到阈值,而不仅仅是非零。也支持等待非零阈值,但我上一句话暗示
- 每个unix上的信号量资源都非常有限。您可以使用“ipcs”命令检查这些
- System V 信号量有一个撤消功能,因此您可以确保异常程序终止不会使您的信号量处于不希望的状态
回答by parasrish
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;
}
回答by Gyan Prakash
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;
}

