linux 다중 루틴의 루틴 제어와 루틴 통신

11260 단어
1. Linux 스레드 개념
프로세스와 루틴 사이에는 차이가 있지만, 리눅스 핵은 가벼운 프로세스만 지원하고, 이른바 루틴은 본질적으로 핵에서 여전히 프로세스이다.
프로세스는 자원 분배의 단위로 같은 프로세스의 여러 라인이 프로세스의 자원을 공유한다.리눅스의 루틴은 생성될 때만 부모 프로세스의 자원을 가지고 있기 때문에 clone에서 나오는 프로세스는 루틴으로 표현되며 부모 프로세스 자원을 공유하는 특성이 있습니다.
프로그램과 루틴 라이브러리를 연결하면 Linux 플랫폼의 다중 루틴을 지원할 수 있으며, 프로그램에 헤더 파일 pthread를 포함해야 한다.h, 링크 컴파일 시 명령 사용: gcc-D -REENTRANT -lpthread xxx.c
그 중에서 -REENTRANT 매크로는 관련 라이브러리 함수(예를 들어 stdio.h,errno.h의 함수)를 리셋할 수 있고 라인이 안전하다(thread-safe),-lpthread는 링크 라이브러리 디렉터리의libpthread를 의미한다.a 또는 libpthread.서류
유행하는 스레드 모델에는 LinuxThreads와 NPTL이 있습니다.스레드 라이브러리를 사용하려면 2.0 이상의 리눅스 라이브러리와 해당 버전의 C 라이브러리(libc 또는glibc)가 필요하다.
참조:http://www.ibm.com/developerworks/cn/linux/l-threading.html
2. 스레드 제어
(1) 스레드 생성
프로세스가 생성되면 시스템이 주 루틴을 만들고 프로세스에 새 루틴을 만들려면 pthreadcreate: 
pthread_create(pthread_t *thread, const pthread_attr_t *attr, void * (start_routine)(void*), void *arg);
start_routine은 새 라인의 입구 함수이고,arg는 start 에 전달됩니다routine의 매개변수입니다.프로세스 내에서 구분할 수 있도록 각 스레드에는 고유한 스레드 ID가 있습니다.pthread에서 스레드 IDcreate 호출 시 라인을 만든 호출자에게 되돌려주기;하나의 스레드도 창설 후 pthread 를 사용할 수 있습니다self () 호출은 자신의 스레드 ID를 가져옵니다.
pthread_self (void) ;
(2) 스레드 종료
스레드를 종료하는 방법:
1) 수행 완료 후 암시적 종료
2) 스레드 자체에 의해 Pthread 호출 표시됨exit 함수 종료
pthread_exit (void * retval) ;
3) 다른 스레드에 의해 pthreadcance 함수 종료
pthread_cance (pthread_t thread) ;
어떤 라인에서 이 함수를 호출하면 매개 변수thread가 지정한 라인을 종료할 수 있습니다.만약 한 라인이 다른 라인의 종료를 기다리려면pthreadjoin 함수, 이 함수의 역할은 pthread 호출join의 스레드는 스레드 ID가 thread인 스레드가 종료될 때까지 보류됩니다.
pthread_join (pthread_t thread, void** threadreturn);
3. 스레드 통신
(1) 스레드 상호 배척
상호 배척은 두 라인이 상호 배척 보호된 코드에 동시에 들어갈 수 없다는 것을 의미한다.Linux에서 pthreadmutex_l 정의 상호 배척체 메커니즘은 여러 라인의 상호 배척 조작을 완성한다. 이 메커니즘의 역할은 상호 배척이 필요한 부분에 대해 들어갈 때 상호 배척체를 먼저 얻는다. 만약에 상호 배척체를 얻지 못하면 상호 배척 부분은 다른 라인에 의해 보유된 것을 나타낸다. 이때 상호 배척체를 얻으려고 하는 라인은 이 배척체를 가진 라인이 상호 배척 부분의 조작을 완성할 때까지 막힌다. 
다음 코드는 공유 글로벌 변수 x1을 상호 배타적 mutex로 보호하는 목적을 실현했습니다.
int x1; //          
pthread_mutex_t mutex; 
pthread_mutex_init(&mutex, NULL); //              mutex 
pthread_mutex_lock(&mutex); //          
… //   x1     
phtread_mutex_unlock(&mutex); //          

(2) 스레드 동기화
동기화는 어떤 사건의 발생을 기다리는 라인이다.기다리는 이벤트가 발생할 때만 라인이 계속 실행됩니다. 그렇지 않으면 라인이 끊기고 프로세서를 포기합니다.여러 라인이 협업할 때 상호작용하는 임무는 반드시 일정한 조건하에서 동기화되어야 한다. 
1) 조건 변수 Linux의 C 언어 프로그래밍에는 여러 스레드 동기화 메커니즘이 있는데 가장 전형적인 것은 조건 변수(condition variable)다.
pthread_cond_init는 다음과 같은 조건 변수를 만드는 데 사용됩니다.
pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr);
pthread_cond_wait와 pthreadcond_시간dwait는 조건 변수가 설정되기를 기다리는 데 사용됩니다. 주의해야 할 것은 이 두 대기 호출은 잠긴 상호 배척체 mutex가 필요합니다. 이것은 진정으로 대기 상태에 들어가기 전에 다른 라인이 조건 변수를 설정하여 경쟁을 일으킬 수 있음을 방지하기 위해서입니다.
pthread_cond_wait의 함수 원형은 다음과 같습니다.
pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex);
pthread_cond_broadcast는 이벤트가 발생해도 이벤트를 기다리는 루틴이 더 이상 막히지 않도록 조건 변수를 설정합니다.
pthread_cond_broadcast (pthread_cond_t *cond) ; pthread_cond_signal 은 대기 스레드의 차단 상태를 해제하는 데 사용됩니다.
pthread_cond_signal (pthread_cond_t *cond) ;
pthread_cond_destroy(pthread cond t *cond)는 조건 변수의 자원을 방출하는 데 사용됩니다. 
pthread_cond_destroy(pthread_cond_t *cond) ;
pthread_cond_timedwait 타이머 대기 방식
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
주어진 시간 전에 조건이 충족되지 않으면 ETIMEOUT로 돌아가 기다림을 끝냅니다. 그 중에서 abstime는 타임() 시스템 호출과 같은 의미의 절대 시간 형식으로 나타납니다. 0은 그리니치 시간 1970년 1월 1일 0시 0분 0초를 나타냅니다.
pthread_cond_timedwait 및 pthreadcond_wait, 여러 라인이 동시에 pthread 를 요청하는 것을 방지하기 위해 서로 밀어내는 자물쇠와 협조해야 합니다cond_wait()(또는 pthread cond timedwait(), 아래와 같음)의 경쟁 조건(Race Condition)입니다.mutex 상호 배척 잠금은 일반 잠금(PTHREAD MUTEX TIMED NP) 또는 적응 잠금(PTHREAD MUTEX ADAPTIVE NP)이어야 하며 pthread 을 호출해야 합니다.cond_wait () 전에는 이 스레드가 잠겨 있어야 합니다 (pthread mutex lock (). 조건을 업데이트하기 전에 대기열을 기다리기 전에, mutex는 잠긴 상태를 유지하고, 스레드가 끊기고 대기열에 들어가기 전에 잠금을 해제합니다.조건이 충족되면 pthread 를 떠납니다cond_wait () 이전에, mutex는 pthread 에 들어갈 수 있도록 다시 잠깁니다.cond_wait () 앞의 잠금 동작이 대응합니다.
자극 조건은 두 가지 형식이 있는데, pthreadcond_signal () 이 조건을 기다리는 라인을 활성화합니다. 여러 개의 대기 라인이 존재할 때 입대 순서대로 그 중 하나를 활성화합니다.Pthreadcond_broadcast () 는 모든 대기 라인을 활성화합니다.
조건 변수 인스턴스 1:
이름의 생산자/소비자 문제를 예로 들어 리눅스 라인의 통제와 통신을 논술한다.한 조의 생산자 라인과 한 조의 소비자 라인이 버퍼 구역을 통해 관계를 맺는다.생산자 라인은 생산된 제품을 완충 구역에 보내고 소비자 라인은 그 중에서 제품을 꺼낸다.버퍼는 N 개로 고리 모양의 버퍼입니다. 
#include <stdio.h>
#include <pthread.h>
#define BUFFER_SIZE 16 //      

//          
struct prodcons
{
    int buffer[BUFFER_SIZE]; /*          */
    pthread_mutex_t lock; /*    lock             */
    int readpos, writepos; /*     */
    pthread_cond_t notempty; /*           (         ) */
    pthread_cond_t notfull; /*            (         )*/
};

/*          */
void init(struct prodcons *b)
{
    pthread_mutex_init(&b->lock, NULL);
    pthread_cond_init(&b->notempty, NULL);
    pthread_cond_init(&b->notfull, NULL);
    b->readpos = 0;
    b->writepos = 0;
}
/*         ,         */
void put(struct prodcons *b, int data)
{
    pthread_mutex_lock(&b->lock);
    /*        */
    if ((b->writepos + 1) % BUFFER_SIZE == b->readpos)
    {
        pthread_cond_wait(&b->notfull, &b->lock);//    ,        
    }
    /*    ,      */
    b->buffer[b->writepos] = data;
    b->writepos++;
    if (b->writepos >= BUFFER_SIZE)
        b->writepos = 0;
    /*             */
    if (b->writepos == (b->readpos + 1) % BUFFER_SIZE)//      
    pthread_cond_signal(&b->notempty);//      ,       
    pthread_mutex_unlock(&b->lock);
} 
/*          */
int get(struct prodcons *b)
{
    int data;
    pthread_mutex_lock(&b->lock);
    /*        */
    if (b->writepos == b->readpos)
    {
        pthread_cond_wait(&b->notempty, &b->lock);//          
    }
    /*    ,     */
    data = b->buffer[b->readpos];
    b->readpos++;
    if (b->readpos >= BUFFER_SIZE)
        b->readpos = 0;
    /*             */
    if ((b->writepos + 2) % BUFFER_SIZE == b->readpos)//      
    pthread_cond_signal(&b->notfull);//         
    pthread_mutex_unlock(&b->lock);
    return data;
}

/*   :      1  10000         ,    
             ,       */
#define OVER ( - 1)
struct prodcons buffer;
void *producer(void *data)
{
    int n;
    for (n = 0; n < 10000; n++)
    {
        printf("%d --->
", n); put(&buffer, n); } put(&buffer, OVER); return NULL; } void *consumer(void *data) { int d; while (1) { d = get(&buffer); if (d == OVER) break; printf("--->%d
", d); } return NULL; } int main(void) { pthread_t th_a, th_b; void *retval; init(&buffer); /* */ pthread_create(&th_a, NULL, producer, 0); pthread_create(&th_b, NULL, consumer, 0); /* */ pthread_join(th_a, &retval); pthread_join(th_b, &retval); return 0; }

조건 변수 인스턴스 2:
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

struct node
{
    intn_number;
    structnode *n_next;
} *head = NULL; /*[thread_func]*/


/*       */
static void cleanup_handler(void*arg)
{
    printf("Cleanup handler of second thread.
"); free(arg); pthread_mutex_unlock(&mtx); } static void* thread_func(void*arg) { structnode *p = NULL; pthread_cleanup_push(cleanup_handler, p);//pthread_cond_wait , while(1) { pthread_mutex_lock(&mtx); // mutex_lock wait , // wait , , Head // , // while , pthread_cond_wait , // while (head == NULL) ? pthread_cond_wait // , head == NULL, // 。 , // pthread_cond_wait //( if while(head == NULL) , while(head == NULL) ) while(head == NULL) { pthread_cond_wait(&cond, &mtx); // pthread_cond_wait pthread_mutex_lock mtx, // , //( , , // pthread_mutex_lock(&mtx);, // /*block-->unlock-->wait() return-->lock*/ } p = head; head = head->n_next; printf("Got %d from front of queue
", p->n_number); free(p); pthread_mutex_unlock(&mtx);// , } pthread_cleanup_pop(0); return0; } int main(void) { pthread_t tid; inti; structnode *p; pthread_create(&tid, NULL, thread_func, NULL); // , , // , // , , for(i = 0; i < 10; i++) { p = (struct node *)malloc(sizeof(struct node));// p->n_number = i; pthread_mutex_lock(&mtx);// head , ( pthread_cond_signal , ) p->n_next = head;// head = p; pthread_cond_signal(&cond);// pthread_mutex_unlock(&mtx);// sleep(1); } printf("thread 1 wanna end the cancel thread 2.
"); pthread_cancel(tid); // pthread_cancel, , , // , , , // pthread_cond_wait() 。 pthread_join(tid, NULL); printf("All done -- exiting
"); return0; }

2) 헤더 파일 semaphore에 신호량이 있습니다.h에서 정의한 신호량은 상호 배척체와 조건 변수의 봉인을 완성했고 다중 루틴 프로그램 설계에서 접근 제어 메커니즘에 따라 자원에 대한 동기화 접근을 제어하여 프로그램 설계자에게 더욱 편리한 호출 인터페이스를 제공한다. 
sem_init(sem_t *sem, int pshared, unsigned int val);
이 함수는 신호량sem의 값을 val로 초기화합니다. 매개 변수 pshared는 공유 속성 제어로 프로세스 간에 공유되는지 여부를 나타냅니다. 
sem_wait(sem_t *sem);
이 함수를 호출할 때sem가 무상태일 경우 호출 라인이 막히면 신호량sem값이 증가(post)하여 신호상태가 됩니다.만약sem가 상태가 있다면, 라인 순서를 호출하여 실행하지만, 신호량의 값은 1로 줄입니다.
sem_post(sem_t *sem); 
이 함수를 호출하면 신호량sem의 값이 증가하여 무신호 상태에서 유신호 상태로 바꿀 수 있다.
    
 
4, WIN32, Linux 스레드 함수 비교
win32와 linux의 루틴 제어와 루틴 통신 함수에 대해 본질적인 내용은 일치합니다.인터페이스는 다음과 같습니다.
사항.
WIN32
Linux
 
스레드 생성
CreateThread
pthread_create
 
스레드 종료
실행이 완료되면 종료하기;스레드 자체가 ExitThread 함수를 호출하면 자신을 종료합니다.다른 스레드에 의해 호출된 함수TerminateThread 함수
실행이 완료되면 종료하기;스레드 자체에서 pthread 호출exit 종료;다른 스레드에 호출된 함수 pthreadcance 종료
 
스레드 ID 가져오기
GetCurrentThreadId
pthread_self
 
상호 배척 생성
CreateMutex
pthread_mutex_init
 
상호 배척을 얻다
WaitForSingleObject、WaitForMultipleObjects
pthread_mutex_lock
 
서로 배척하다.
ReleaseMutex
phtread_mutex_unlock
 
신호량 생성
CreateSemaphore
sem_init
 
대기 신호량
WaitForSingleObject
sem_wait
 
방출 신호량
ReleaseSemaphore
sem_post

좋은 웹페이지 즐겨찾기