제12장 POSIX 스레드(둘)
신호량은 특수한 유형의 변수로 증가하거나 감소할 수 있지만, 관건적인 접근은 원자 조작으로 보장된다. 설령 다중 루틴 프로그램에서도 마찬가지다.이것은 만약 한 프로그램에서 두 개의 (또는 더 많은) 라인이 신호량의 값을 바꾸려고 시도한다면 시스템은 모든 조작이 순서대로 진행될 것을 보장할 것이다.그러나 일반 변수라면 같은 프로그램에서 온 서로 다른 라인의 충돌 조작으로 인한 결과는 확실하지 않을 것이다.
신호량 - 이진 신호량으로 0과 1 두 가지 값만 얻을 수 있다.또 하나의 더 통용되는 신호량인 계수 신호량은 더 큰 수치 범위를 가질 수 있다.신호량은 일반적으로 코드를 보호하는 데 사용되며, 매번 하나의 실행 라인에서만 실행될 수 있도록 이 작업을 완성해야 한다.이진 신호량을 사용해야 한다.계수 신호량이 자주 쓰이지 않기 때문이다.그래서 우리는 여기서 그것에 대해 깊이 있게 소개하지 않는다. 사실상 그것은 2진 신호량의 논리적 확장일 뿐이고 두 가지 실제 호출된 함수는 모두 같다.
신호량 통과seminit 함수는 다음과 같이 정의되어 생성됩니다.
#include
int sem_init ( sem_t *sem, int pshared, unsigned int value);
이 함수는 Sem이 가리키는 신호량 대상을 초기화하고 공유 옵션을 설정하며 초기 정수 값을 줍니다.pshared 매개 변수는 신호량의 유형을 제어합니다. 만약 그 값이 0이라면 이 신호량은 현재 프로세스의 것입니다
국부 신호량, 그렇지 않으면 이 신호량은 여러 프로세스 사이에서 공유할 수 있다.
다음 두 함수는 다음과 같이 정의된 신호량의 값을 제어합니다.
#include
int sem_wait (sem_t *sem);
int sem_post (sem_t *sem);
이 두 함수는 모두 하나의 바늘을 매개 변수로 하고, 이 바늘이 가리키는 대상은sem 이다init에서 초기화된 신호량을 호출합니다.
sem_post 함수의 작용은 원자 조작 방식으로 신호량의 값을 1로 더하는 것이다.원자 조작이란 두 개의 루틴이 하나의 신호량에 1을 더하려고 하면 서로 간섭하지 않고, 두 프로그램이 한 파일을 동시에 읽기, 증가, 쓰기 작업을 할 때 충돌을 일으킬 수 있는 것이 아니다.신호량의 값은 두 개의 라인이 그것을 바꾸려고 하기 때문에 항상 정확하게 2를 더해진다.
sem_wait 함수는 원자 조작 방식으로 신호량을 1로 줄이지만, 신호량이 0이 아닌 값이 있을 때까지 기다려야 감법 조작이 시작된다.따라서 만약 값이 2인 신호량에 대해sem 를 호출한다면wait, 라인은 계속 실행되지만, 신호량의 값은 1로 감소합니다.0의 신호량에 대해sem 호출하기wait, 이 함수는 다른 라인이 이 신호량의 값을 증가시켜 0이 되지 않도록 기다릴 것입니다.만약 두 라인이 동시에semwait 호출에서 같은 신호량이 0이 아닌 값으로 바뀌기를 기다리면 이 신호량이 세 번째 라인에 의해 1이 증가할 때 그 중 한 개의 대기 라인만 신호량을 1로 줄이고 계속 실행하며 다른 라인은 계속 기다릴 것입니다.신호량의 이런'단일 함수에서 원자적으로 테스트와 설정을 할 수 있다'는 능력은 그것을 매우 가치 있게 한다.
또 다른 신호량 함수semtrywait, 이것은semwait의 비저항 버전입니다.
sem_Destroy, 이 함수의 역할은 신호량을 다 사용한 후에 그것을 정리하는 것이다.정의는 다음과 같습니다.
#include
int sem_destroy (sem_t *sem);
이 함수도 하나의 신호량 바늘을 매개 변수로 하고 이 신호량이 가지고 있는 모든 자원을 정리합니다.청소하려는 신호량이 일부 라인에서 기다리고 있으면 오류가 발생합니다. 성공할 때 0으로 되돌아옵니다.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
void *thread_function(void *arg);
sem_t bin_sem;
#define WORK_SIZE 1024
char work_area[WORK_SIZE];
int main() {
int res;
pthread_t a_thread;
void *thread_result;
res = sem_init(&bin_sem, 0, 0);
if (res != 0) {
perror("Semaphore initialization failed");
exit(EXIT_FAILURE);
}
res = pthread_create(&a_thread, NULL, thread_function, NULL);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
printf("Input some text. Enter 'end' to finish
");
while(strncmp("end", work_area, 3) != 0) {
fgets(work_area, WORK_SIZE, stdin);
sem_post(&bin_sem);
}
printf("
Waiting for thread to finish...
");
res = pthread_join(a_thread, &thread_result);
if (res != 0) {
perror("Thread join failed");
exit(EXIT_FAILURE);
}
printf("Thread joined
");
sem_destroy(&bin_sem);
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg) {
sem_wait(&bin_sem);
while(strncmp("end", work_area, 3) != 0) {
printf("You input %d characters
", strlen(work_area) -1);
sem_wait(&bin_sem);
}
pthread_exit(NULL);
}
프로그램 실행:
$./thread3 Input some text. Enter ‘end’ to finish The Wasp Factory You input 16 characters Iain Banks You input 10 characters end Waiting for thread to finish... Thread joined
실험 분석:
신호량을 초기화할 때, 우리는 그것의 값을 0으로 설정합니다.이렇게 해서 스레드 함수가 시작될 때semwait 함수 호출은 신호량이 0이 아닌 값으로 바뀌기를 막고 기다립니다.
주 라인에서 텍스트 입력이 있을 때까지 기다린 다음sem 를 호출합니다post 신호량의 값을 증가하면 다른 라인이sem 에서 즉시wait의 대기 중 되돌아와 실행을 시작합니다.문자 개수를 집계한 후,sem 를 다시 호출합니다주 라인이sem 를 다시 호출할 때까지 wait 및 다시 막힘post가 신호량을 증가시킬 때까지
우리는 프로그램 설계상의 미세한 오류를 무시하기 쉬우며, 이 오류는 프로그램 운행 결과의 일부 미세한 오류를 초래할 수 있다.위의 절차는 다음과 같이 수정됩니다.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
void *thread_function(void *arg);
sem_t bin_sem;
#define WORK_SIZE 1024
char work_area[WORK_SIZE];
int main() {
int res;
pthread_t a_thread;
void *thread_result;
res = sem_init(&bin_sem, 0, 0);
if (res != 0) {
perror("Semaphore initialization failed");
exit(EXIT_FAILURE);
}
res = pthread_create(&a_thread, NULL, thread_function, NULL);
if (res != 0) {
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
printf("Input some text. Enter 'end' to finish
");
while(strncmp("end", work_area, 3) != 0) {
if (strncmp(work_area, "FAST", 4) == 0) {
sem_post(&bin_sem);
strcpy(work_area, "Wheeee...");
} else {
fgets(work_area, WORK_SIZE, stdin);
}
sem_post(&bin_sem);
}
printf("
Waiting for thread to finish...
");
res = pthread_join(a_thread, &thread_result);
if (res != 0) {
perror("Thread join failed");
exit(EXIT_FAILURE);
}
printf("Thread joined
");
sem_destroy(&bin_sem);
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg) {
sem_wait(&bin_sem);
while(strncmp("end", work_area, 3) != 0) {
printf("You input %d characters
", strlen(work_area) -1);
sem_wait(&bin_sem);
}
pthread_exit(NULL);
}
F.A.S.T. 입력
$ ./thread3a Input some text. Enter ‘end’ to finish Excession You input 9 characters FAST You input 7 characters You input 7 characters You input 7 characters end Waiting for thread to finish... Thread joined
문제는 프로그램이 텍스트 입력을 받는 시간이 충분해야 다른 라인이 주 라인에서 더 많은 단어를 통계하기 전에 작업 영역의 문자의 개수를 통계할 수 있다는 점이다.우리가 두 그룹의 다른 단어를 연속적으로 신속하게 통계하려고 시도할 때 (키보드에 입력한 F.A.S.T.와 프로그램이 자동으로 제공하는 Weee...)두 번째 라인은 실행할 시간이 없다.그러나 신호량이 한 번도 증가하지 않았기 때문에 문자 통계 라인은 다시 0이 될 때까지 문자 수를 반복적으로 통계하고 신호량의 값을 감소시킨다.이 예는 다중 루틴 프로그램에서 우리는 여러 시기를 꼼꼼하게 고려해야 한다는 것을 보여 준다.상기 프로그램의 문제를 해결하기 위해 우리는 하나의 신호량을 더 늘려 주 라인이 통계 라인이 문자 개수의 통계를 완성한 후에 계속 집행하도록 할 수 있지만 더욱 간단한 방식은 상호 배척량을 사용하는 것이다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.