Linux 신 호 량 생산자 소비자 사례
28406 단어 생산자 소비자
제목: http://www.it165.net/os/html/201312/7039.html
신 호 량 및 그 용법: http://www.cnblogs.com/hjslovewcl/archive/2011/03/03/2314341.html
Mutex 와 Semaphore 의 구별 이 유명한 화장실 이론: http://koti.mbnet.fi/niclasw/MutexSemaphore.html
아이고, 들 켰 다!나 는 고의로 다른 사람 을 훔 쳐 본 것 이 아니다.
1. 생산자, 소비자, 자원 현황
이러한 상황 은 하나의 신 호 량 만 사용 할 수 있 습 니 다. 생 성 하거나 소비 하려 면 이 신 호 량 만 얻 으 려 고 합 니 다. 여 기 는 full = 1 과 empty = 0 을 사 용 했 습 니 다. 두 개 는 뒤쪽 과 일치 하기 위해 서 입 니 다. 1, 0 은 초기 값 입 니 다.생산자 와 소비자 의 상황 은 다음 과 같다.
// :
P(empty)
V(full)
// :
P(full)
V(empty)
생산자 가 가장 먼저 자원 을 생산 하기 시작 하면 P (empty), full 과 empty 는 모두 0 이 된다. 이때 소비자 가 소비 하고 싶 으 면 P (full) 일 때 full 이 0 이면 잠 을 자고 기다린다. 생산자 가 태 어 나 면 full 을 1 로 더 하고 소비자 가 불쌍 하 게 잠 든 것 을 보면 깨 우 고 소비 자 는 full 을 1 로 줄 여 스스로 즐겁게 한다.
소비자 소비 과정 에서 생산자 가 낳 으 려 면 empty 가 0 이 라 휴면 하고 소비자 가 끝나 면 empty 를 1 로 더 한 후 생산자 가 생산 을 시작한다.
위의 것 은 이해 하기 쉽 고 아래 의 코드 는:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <x86_64-linux-gnu/sys/types.h>
#include <x86_64-linux-gnu/sys/ipc.h>
#include <x86_64-linux-gnu/sys/sem.h>
int semInite(int semId, int value);
int semDelete(int semId);
int semP(int semId);
int semV(int semId);
//declare a union to be used
union semun
{
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
unsigned short int *array; /* array for GETALL, SETALL */
struct seminfo *__buf; /* buffer for IPC_INFO */
};
//semaphore declare
static int semFullId;
static int semEmptyId;
static int source = 0; //source definition
//new thread as a consumer
void* child_thread(void* arg)
{
int ttt = 1;
while(1)
{
sleep(rand() % 19);
printf("child No.%d times wants to consume...
", ttt);
semP(semFullId); //
printf("child No.%d times start consuming. source = %d
", ttt, source);
source = 0;
printf("child No.%d times end consuming. source = %d
", ttt++, source);
semV(semEmptyId); //
}
return (void*)0;
}
int main(void)
{
//create semaphore
semFullId = semget((key_t)1235, 1, 0666 | IPC_CREAT);
semEmptyId = semget((key_t)1236, 1, 0666 | IPC_CREAT);
semInite(semFullId, 0);
semInite(semEmptyId, 1);
pthread_t pid;
pthread_create(&pid, NULL, child_thread, NULL);
int tt = 1;
while(1)
{
sleep(rand() % 18);
printf("parent No.%d times wants to produce...
", tt);
semP(semEmptyId); //
printf("parent No.%d times start producing. source = %d
", tt, source);
source = rand() % 100;
printf("parent No.%d times end producing. source = %d
", tt++, source);
semV(semFullId); //
}
semDelete(semFullId);
semDelete(semEmptyId);
return 0;
}
//set semaphore as default value
int semInite(int semId, int value)
{
union semun semUnion;
semUnion.val = value; //set default semaphore
return semctl(semId, 0, SETVAL, semUnion);
}
//delete semaphore
int semDelete(int semId)
{
union semun semUnion;
return semctl(semId, 0, IPC_RMID, semUnion);
}
//semaphore P operation
int semP(int semId)
{
struct sembuf semBuf;
semBuf.sem_num = 0; //indicate it is not semaphore array
semBuf.sem_op = -1; //subtract one
semBuf.sem_flg = SEM_UNDO;
return semop(semId, &semBuf, 1); //return value
}
//semaphore V operation
int semV(int semId)
{
struct sembuf semBuf;
semBuf.sem_num = 0; //indicate it is not semaphore array
semBuf.sem_op = 1; //subtract one
semBuf.sem_flg = SEM_UNDO;
return semop(semId, &semBuf, 1); //return value
}
111
두 신 호 량 은 사실 신 호 량 으로 집합 해 야 한다. 왜냐하면 그것 은 원래 집합 을 겨냥 한 것 이기 때문이다. 그러나 막 입문 하기 때문에 이해 하기 위해 두 개 를 사용한다.두 스 레 드, 새로 만 든 스 레 드 를 소비자 로 삼 았 습 니 다.그 중에서 유 닉 스 의 몇 가지 신 호 량 의 함 수 를 반나절 동안 보 았 는데 좀 복잡 합 니 다. 쉽게 말 하면 정확 하지 않 습 니 다.
// , ,
// unix , 1
//
int semget(key_t key, int num_sems, int sem_flags);
// , P、V +1 -1
int semop(int sem_id, struct sembuf *sem_ops, size_t num_sem_ops);
// ,
int semctl(int sem_id, int sem_num, int command, ...);
실행:
2. 한 생산자, 한 소비자, N 개 자원 현황
이곳 의 자원 은 하나의 배열 로 대체 되 었 다.사실은 본질 적 으로 위 와 비슷 하 다. 매번 생산자 나 소비자 중 한 명 만 들 어가 게 하고 들 어가 서 어느 곳 에 놓 거나 어느 곳 에서 찾 으 면 하나의 표지 로 설명 해 야 한다. 사실은 모든 자원 에 신 호 량 을 더 할 수 있다.
여기 서 생산자 와 소비자 에 게 static 변 수 를 커서 로 설정 하여 다음 자원 을 어느 위치 에 두 고 다음 에 어디서 자원 을 찾 는 지 알려 줍 니 다.staitic 변 수 는 한 번 만 초기 화 되 기 때문에 여기에 사용 하기에 적합 합 니 다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <x86_64-linux-gnu/sys/types.h>
#include <x86_64-linux-gnu/sys/ipc.h>
#include <x86_64-linux-gnu/sys/sem.h>
#define N 5
int semInite(int semId, int value);
int semDelete(int semId);
int semP(int semId);
int semV(int semId);
//declare a union to be used
union semun
{
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
unsigned short int *array; /* array for GETALL, SETALL */
struct seminfo *__buf; /* buffer for IPC_INFO */
};
//semaphore declare
static int semFullId;
static int semEmptyId;
static int srcArr[N]; //source definition
//new thread as a consumer
void* child_thread(void* arg)
{
int ttt = 1;
while(1)
{
static int pToGet = 0; //get source from the position
sleep(rand() % 19);
printf("child No.%d times wants to consume(get from index %d)...
", ttt, pToGet);
semP(semFullId); //
printf("child No.%d times start consuming.(get from index %d, data is %d)
", ttt, pToGet, srcArr[pToGet]);
srcArr[pToGet] = 0;
printf("child No.%d times end consuming. (get from index %d)
", ttt++, pToGet);
pToGet = (pToGet + 1) % N;
semV(semEmptyId); //
}
return (void*)0;
}
int main(void)
{
//create semaphore
semFullId = semget((key_t)1235, 1, 0666 | IPC_CREAT);
semEmptyId = semget((key_t)1236, 1, 0666 | IPC_CREAT);
semInite(semFullId, 0);
semInite(semEmptyId, N); //N source
pthread_t pid;
pthread_create(&pid, NULL, child_thread, NULL);
int tt = 1;
while(1)
{
static int pToPut = 0; //next position where source to be filled in
sleep(rand() % 18);
printf("parent No.%d times wants to produce(put in %d index)...
", tt, pToPut);
semP(semEmptyId); //
printf("parent No.%d times start producing.(put in %d index, original data is %d)
", tt, pToPut, srcArr[pToPut]);
int temp = rand() % 100;
srcArr[pToPut] = temp;
printf("parent No.%d times end producing.(put in %d index, now data is %d)
", tt++, pToPut, srcArr[pToPut]);
pToPut = (pToPut + 1) % N;
semV(semFullId); //
}
semDelete(semFullId);
semDelete(semEmptyId);
return 0;
}
//set semaphore as default value
int semInite(int semId, int value)
{
union semun semUnion;
semUnion.val = value; //set default semaphore
return semctl(semId, 0, SETVAL, semUnion);
}
//delete semaphore
int semDelete(int semId)
{
union semun semUnion;
return semctl(semId, 0, IPC_RMID, semUnion);
}
//semaphore P operation
int semP(int semId)
{
struct sembuf semBuf;
semBuf.sem_num = 0; //indicate it is not semaphore array
semBuf.sem_op = -1; //subtract one
semBuf.sem_flg = SEM_UNDO;
return semop(semId, &semBuf, 1); //return value
}
//semaphore V operation
int semV(int semId)
{
struct sembuf semBuf;
semBuf.sem_num = 0; //indicate it is not semaphore array
semBuf.sem_op = 1; //subtract one
semBuf.sem_flg = SEM_UNDO;
return semop(semId, &semBuf, 1); //return value
}
222
실행 결과:
3. N 개 생산자, N 개 소비자, N 개 자원
이런 상황 은 생산자 와 소비자 간 에 상술 한 방식 을 통 해 자원 사용 을 조율 해 야 할 뿐만 아니 라 생산자 내부 와 소비자 내부 도 조율 해 야 한다.네 개의 신 호 량 정의:
empty - 버퍼 가 비어 있 는 지, 초기 값 은 n 입 니 다.full - 버퍼 가 가득 찼 는 지, 초기 값 이 0 인지 표시 합 니 다.mutex 1 - 생산자 간 의 상호 배척 신 호 량, 초기 값 은 1 이다.mutex 2 - 소비자 간 의 상호 배척 신 호 량, 초기 값 은 1 이다.
//
P(mutex1)
P(empty)
V(full)
V(mutex1)
//
P(mutex2)
P(full)
V(empty)
V(mutex2)
사실 위의 생산자 나 소비자 가 상호 배척 량 이나 신 호 량 을 얻 는 순 서 는 뒤 바 뀔 수 있 고 자물쇠 가 생기 지 않 는 다.
물론 이 문 제 는 다른 더 좋 은 방법 으로 해결 할 수 있 고 나 는 계속 공부 해 야 한다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JAVA 멀티스레드 생산자 소비자 모델 실현문제 배경: 파충류가 되어 인터넷에서 책을 기어오르고 기어내린 후 데이터베이스에 삽입 문제 설계: 여러 라인으로 동시에 인터넷에서 책을 기어오르고 기어오르는 책은 한 라인을 삽입한다. 이런 라인은 같은 책 대기열을 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.