2
我試圖最終解決生產者 - 消費者問題,但我首先需要能夠使用信號量來創建臨界區。我目前遇到的問題是當我運行程序時,關鍵部分有時會有多個進程進入它。我希望在特定時間只有一個進程處於關鍵部分。這是我目前擁有的代碼:C - 多信號叉與信號量
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define MAX 20
int main(void)
{
key_t key = 1114;
int semid, count,
mutex = 0;
//Initialize Semaphore Buffers
struct sembuf oper0;
pid_t waitId;
pid_t parentId = getpid();
//Create processes
for(count = 0; count < MAX; count++)
{
if((waitId = fork()) == 0)
{
break;
}
}
//Create a semaphore set of 3; I will be adding more semaphores
if ((semid = semget(key, 3, 0600 | IPC_CREAT)) == -1) {
printf("error in semget");
exit(1);
}
// BINARY/MUTEX - initialize semaphore0 to 1
if(semctl(semid, mutex, SETVAL, 1) == -1)
{
printf("error in semctl");
exit(0);
}
//Decrement semaphore 0
oper0.sem_op = -1;
oper0.sem_flg = 0;
if (semop(semid, &oper0, 1) == -1) {
printf("error decrementing semaphore \n");
exit(1);
}
printf(" -- CRITICAL SECTION START ----------- \n\n");
printf("%5d %d %s\n", getpid(), semctl(semid, 0, GETVAL, oper0.sem_num), " -- Semaphore 0");
printf(" -- CRITICAL SECTION END -- \n\n");
//Increments semaphore 0
oper0.sem_op = 1;
oper0.sem_flg = 0;
if (semop(semid, &oper0, 1) == -1) {
printf("error incrementing semaphore \n");
exit(1);
}
int i;
if(getpid() == parentId)
{
for(i = 0; i < MAX i++)
{
wait(&waitId);
}
}
else
{
exit(waitId);
}
// Remove semaphore
if (semctl(semid, 0, IPC_RMID) == -1) {
printf("error in semctl");
exit(1);
}
return 0;
}
下面是一個示例輸出:
-- CRITICAL SECTION START -----------
1097 0 -- Semaphore 0
-- CRITICAL SECTION END --
-- CRITICAL SECTION START -----------
1085 0 -- Semaphore 0
-- CRITICAL SECTION END --
-- CRITICAL SECTION START -----------
-- CRITICAL SECTION START -----------
1095 0 -- Semaphore 0
-- CRITICAL SECTION END --
1093 0 -- Semaphore 0
-- CRITICAL SECTION END --
-- CRITICAL SECTION START -----------
-- CRITICAL SECTION START -----------
1087 0 -- Semaphore 0
-- CRITICAL SECTION END --
1089 0 -- Semaphore 0
-- CRITICAL SECTION END --
-- CRITICAL SECTION START -----------
1091 0 -- Semaphore 0
-- CRITICAL SECTION END --
爲什麼旗語一個過程有時會鎖定,其他時候它可以讓兩個進程嗎?
這很有道理,謝謝!我只是有一個問題來澄清fflush部分。我只需要將fflush(stdout)放在關鍵部分的printf後面,對吧?原因是因爲緩衝區可能無法立即打印,而其他部分可能會在之前打印? –
如果關鍵部分的要點是對stdout進行序列化,那麼在離開臨界區之前應該先進行刷新,並且不要在臨界區之外打印任何內容,這相當於當緩衝區始終爲空時的不變量不在關鍵部分。 (控制檯輸出是行緩衝的,但是如果你重定向到一個文件則不行。) – rici
哦,好的。再次感謝! –