APUE函数笔记十: 线程控制

来源:互联网 发布:淘宝素描是不是打印的 编辑:程序博客网 时间:2024/05/19 22:50

第十二章  线程控制:

#include <pthread.h>int pthread_attr_init(pthread_attr_t * attr);    if success return 0, else return error-no, will not modify errnoint pthread_attr_destroy(pthread_attr_t * attr);    if success return 0, else return error-no, will not modify errno#include <pthread.h>int pthread_attr_getdetachstate(const pthread_attr_t * restrict attr,                                 int * detachstate);    if success return 0, else return error-no, will not modify errnoint pthread_attr_setdetachstate(pthread_attr_t * attr, int detachstate);    if success return 0, else return error-no, will not modify errno    detachstate:        PTHREAD_CREATE_DETACHED        PTHREAD_CREATE_JOINABLE#include <pthread.h>int pthread_attr_getstack(const pthread_attr_t * restrict attr,                           void ** restrict stackaddr,                           size_t * restrict stacksize);    if success return 0, else return error-no, will not modify errnoint pthread_attr_setstack(pthread_attr_t * attr,                           void * stackaddr, size_t stacksize);    if success return 0, else return error-no, will not modify errno#include <pthread.h>int pthread_attr_getstacksize(const pthread_attr_t * restrict attr,                               size_t * restrict stacksize);    if success return 0, else return error-no, will not modify errnoint pthread_attr_setstacksize(pthread_attr_t * attr, size_t stacksize);    if success return 0, else return error-no, will not modify errno#include <pthread.h>int pthread_attr_getguardsize(const pthread_attr_t * restrict attr,                               size_t * restrict guardsize);    if success return 0, else return error-no, will not modify errnoint pthread_attr_setguardsize(pthread_attr_t * attr, size_t guardsize);    if success return 0, else return error-no, will not modify errno#include <pthread.h>int pthread_getconcurrency(void);    return current concurrency, 0 means system defaultint pthread_setconcurrency(int level);    if success return 0, else return error-no, will not modify errno1#include <pthread.h>int pthread_mutexattr_init(pthread_mutexattr_t * attr);    if success return 0, else return error-no, will not modify errnoint pthread_mutexattr_destroy(pthread_mutexattr_t * attr);    if success return 0, else return error-no, will not modify errno#include <pthread.h>int pthread_mutexattr_getpshared(const pthread_mutexattr_t * restrict attr,                                  int * restrict pshared);    if success return 0, else return error-no, will not modify errnoint pthread_mutexattr_setpshared(pthread_mutexattr_t * attr, int pshared);    if success return 0, else return error-no, will not modify errno    pshared:        PTHREAD_PROCESS_PRIVATE  /* for multi-thread */        PTHREAD_PROCESS_SHARED  /* for multi-process */#include <pthread.h>int pthread_mutexattr_gettype(const pthread_mutexattr_t * restrict attr,                               int * restrict type);    if success return 0, else return error-no, will not modify errnoint pthread_mutexattr_settype(pthread_mutexattr_t * attr, int type);    if success return 0, else return error-no, will not modify errno    type:        PTHREAD_MUTEX_NORMAL        PTHREAD_MUTEX_ERRORCHECK        PTHREAD_MUTEX_RECURSIVE        PTHREAD_MUTEX_DEFAULT#include <pthread.h>int pthread_rwlockattr_init(pthread_rwlockattr_t * attr);    if success return 0, else return error-no, will not modify errnoint pthread_rwlockattr_destroy(pthread_rwlockattr_t * attr);    if success return 0, else return error-no, will not modify errno#include <pthread.h>int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t * restrict attr,                                   int * restrict pshared);    if success return 0, else return error-no, will not modify errnoint pthread_rwlockattr_setpshared(pthread_rwlockattr_t * attr, int pshared);    if success return 0, else return error-no, will not modify errno    pshared:        PTHREAD_PROCESS_PRIVATE  /* for multi-thread */        PTHREAD_PROCESS_SHARED  /* for multi-process */#include <pthread.h>int pthread_condattr_init(pthread_condattr_t * attr);    if success return 0, else return error-no, will not modify errnoint pthread_condattr_destroy(pthread_condattr_t * attr);    if success return 0, else return error-no, will not modify errno#include <pthread.h>int pthread_condattr_getpshared(const pthread_condattr_t * restrict attr,                                 int * restrict pshared);    if success return 0, else return error-no, will not modify errnoint pthread_condattr_setpshared(pthread_condattr_t * attr, int pshared);    if success return 0, else return error-no, will not modify errno    pshared:        PTHREAD_PROCESS_PRIVATE  /* for multi-thread */        PTHREAD_PROCESS_SHARED  /* for multi-process */#include <stdio.h>int ftrylockfile(FILE * fp);    if success return 0, else return non-zerovoid flockfile(FILE * fp);void funlockfile(FILE * fp);#include <stdio.h>int getchar_unlock(void);    if error or end-of-file return EOF, if EOF check it with ferror or feofint getc_unlock(FILE * fp);    if error or end-of-file return EOF, if EOF check it with ferror or feofint putchar_unlock(int c);    if success return c, else return EOFint putc_unlock(int c, FILE * fp);    if success return c, else return EOF#include <pthread.h>int pthread_key_create(pthread_key_t * key, void (*destructor)(void *));    if success return 0, else return error-no, will not modify errno#include <pthread.h>int pthread_key_delete(pthread_key_t * key);    if success return 0, else return error-no, will not modify errno#include <pthread.h>pthread_once_t initflag = PTHREAD_ONCE_INIT;int pthread_once(pthread_once_t * initflag, void (*initfn)(void));    if success return 0, else return error-no, will not modify errno#include <pthread.h>void * pthread_getspecific(pthread_key_t key);    return thread private data, if no data match with key return NULLint pthread_setspecific(pthread_key_t key, const void * value);    if success return 0, else return error-no, will not modify errno#include <pthread.h>int pthread_setcancelstate(int state, int * oldstate);    if success return 0, else return error-no, will not modify errno    state:        PTHREAD_CANCEL_ENABLE        PTHREAD_CANCEL_DISABLE#include <pthread.h>void pthread_testcancel(void);#include <pthread.h>int pthread_setcanceltype(int type, int * oldtype);    if success return 0, else return error-no, will not modify errno    type:        PTHREAD_CANCEL_DEFERRED      /* default */        PTHREAD_CANCEL_ASYNCHRONOUS#include <signal.h>int pthread_sigmask(int how, const sigset_t * restrict set,                     sigset_t * restrict oset);    if success return 0, else return error-no, will not modify errno#include <signal.h>int sigwait(const sigset_t * restrict set, int * restrict signop);    if success return 0, else return error-no, will not modify errno#include <signal.h>int pthread_kill(pthread_t thread, int signo);    if success return 0, else return error-no, will not modify errno#include <pthread.h>int pthread_atfork(void (*prepare)(void),                    void (*parent)(void),                    void (*child)(void));    if success return 0, else return error-no, will not modify errno

示例:

#include <stdio.h>#include <stdlib.h>#include <sys/time.h>#include <pthread.h>struct to_info {    void (*to_fn)(void *);   /* function */    void * to_arg;           /* argument */     struct timespec to_wait; /* time to wait */};int makethread(void * (*fn)(void *), void * arg, int detach){    int             err;    int             detachstate;    pthread_t       tid;    pthread_attr_t  attr;    if ((err = pthread_attr_init(&attr)) != 0) {        return(err);    }    if (detach != 0) {        detachstate = PTHREAD_CREATE_DETACHED;    }    else {        detachstate = PTHREAD_CREATE_JOINABLE;    }    err = pthread_attr_setdetachstate(&attr, detachstate);    if (err == 0) {        err = pthread_create(&tid, &attr, fn, arg);    }    pthread_attr_destroy(&attr);    return(err);}void * timeout_helper(void * arg){    struct to_info * tip;    tip = (struct to_info *)arg;    nanosleep(&tip->to_wait, NULL);    (*tip->to_fn)(tip->to_arg);    free(arg);    return((void *)0);}void timeout(const struct timespec * when, void (*func)(void *), void * arg){    struct timespec  now;    struct timeval   tv;    struct to_info * tip;    int              err;    gettimeofday(&tv, NULL);    now.tv_sec = tv.tv_sec;    now.tv_nsec = tv.tv_usec * 1000;    if ((when->tv_sec > now.tv_sec) ||         (when->tv_sec == now.tv_sec && when->tv_nsec > now.tv_nsec)) {        tip = (struct to_info *)malloc(sizeof(struct to_info));        if (tip != NULL) {            tip->to_fn = func;            tip->to_arg = arg;            tip->to_wait.tv_sec = when->tv_sec - now.tv_sec;            if (when->tv_nsec >= now.tv_nsec) {                tip->to_wait.tv_nsec = when->tv_nsec - now.tv_nsec;            }            else {                --tip->to_wait.tv_sec;                tip->to_wait.tv_nsec = 1000000000 - now.tv_nsec + when->tv_nsec;            }            err = makethread(timeout_helper, tip, 1);            if (err == 0) {                return;            }            else {                free(tip);            }        }    }    (*func)(arg);}pthread_mutexattr_t attr;pthread_mutex_t mutex;void retry(void * arg){    pthread_mutex_lock(&mutex);    /* ... perform retry steps ... */    printf("it is a test\n");    pthread_mutex_unlock(&mutex);}void maketimespec(struct timespec * tsp, long seconds){    struct timeval now;    gettimeofday(&now, NULL);    tsp->tv_sec = now.tv_sec;    tsp->tv_nsec = now.tv_usec * 1000;    tsp->tv_sec += seconds;}int main(void){    int             err;    int             condition;    int             arg;    struct timespec when;    if ((err = pthread_mutexattr_init(&attr)) != 0) {        printf("pthread_mutexattr_init failed\n");        return(1);    }    err = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);    if (err != 0) {        printf("pthread_mutexattr_settype failed\n");    }    else if ((err = pthread_mutex_init(&mutex, &attr)) != 0) {        printf("pthread_mutex_init failed\n");    }    pthread_mutexattr_destroy(&attr);    if (err != 0) {        return(1);    }    /* ... */    pthread_mutex_lock(&mutex);    condition = 1;    if (condition) {        /* calculate target time "when" */        maketimespec(&when, 5);        timeout(&when, retry, (void *)arg);    }    /* ... */    pthread_mutex_unlock(&mutex);    /* ... */    sleep(10); /* wait */    exit(0); /* fflush */}

#include <limits.h>#include <string.h>#define ARG_MAX (256)char envbuf[ARG_MAX];extern char ** environ;char * getenv(const char * name){    int i;    int len;    len = strlen(name);    for (i = 0; environ[i] != NULL; ++i) {        if ((strncmp(name, environ[i], len) == 0) &&             (environ[i][len] = '=')) {            strcpy(envbuf, &environ[i][len + 1]);            return(envbuf);        }    }    return(NULL);}

#include <string.h>#include <errno.h>#include <pthread.h>#include <stdlib.h>extern char ** environ;pthread_mutex_t env_mutex;pthread_once_t init_done = PTHREAD_ONCE_INIT;void thread_init(void){    pthread_mutexattr_t attr;    pthread_mutexattr_init(&attr);    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);    pthread_mutex_init(&env_mutex, &attr);    pthread_mutexattr_destroy(&attr);}int getenv_r(const char * name, char * buf, int buflen){    int i;    int len;    int olen;    pthread_once(&init_done, thread_init);    len = strlen(name);    pthread_mutex_lock(&env_mutex);    for (i = 0; environ[i] != NULL; ++i) {        if ((strncmp(name, environ[i], len) == 0) &&             (environ[i][len] == '=')) {            olen = strlen(&environ[i][len + 1]);            if (olen >= buflen) {                pthread_mutex_unlock(&env_mutex);                return(ENOSPC);            }            else {                strcpy(buf, &environ[i][len + 1]);                pthread_mutex_unlock(&env_mutex);                return(0);            }        }    }    pthread_mutex_unlock(&env_mutex);    return(ENOENT);}

#include <stdlib.h>#include <limits.h>#include <string.h>#include <pthread.h>#define ARG_MAX  (256)pthread_key_t key;pthread_once_t init_done = PTHREAD_ONCE_INIT;pthread_mutex_t env_mutex = PTHREAD_MUTEX_INITIALIZER;extern char ** environ;void thread_init(void){    pthread_key_create(&key, free);}char * getenv(const char * name){    int    i;    int    len;    char * envbuf;    pthread_once(&init_done, thread_init);    pthread_mutex_lock(&env_mutex);    envbuf = (char *)pthread_getspecific(key);    if (envbuf == NULL) {        envbuf = (char *)malloc(ARG_MAX);        if (envbuf == NULL) {            pthread_mutex_unlock(&env_mutex);            return(NULL);        }        pthread_setspecific(key, envbuf);    }    len = strlen(name);    for (i = 0; environ[i] != NULL; ++i) {        if ((strncmp(name, environ[i], len) == 0) &&             (environ[i][len] == '=')) {            strcpy(envbuf, &environ[i][len + 1]);            pthread_mutex_unlock(&env_mutex);            return(envbuf);        }    }    pthread_mutex_unlock(&env_mutex);    return(NULL);}

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <signal.h>#include <pthread.h>int       quitflag; /* set nonzero by thread */sigset_t  mask;pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t wait = PTHREAD_COND_INITIALIZER;void * thr_fn(void * arg){    int err;    int signo;    for (;;) {        err = sigwait(&mask, &signo);        if (err != 0) {            printf("sigwait failed: %s\n", strerror(err));            exit(1);        }        switch (signo) {            case SIGINT:            {                printf("\ninterrupt\n");                break;            }            case SIGQUIT:            {                pthread_mutex_lock(&lock);                quitflag = 1;                pthread_mutex_unlock(&lock);                pthread_cond_signal(&wait);                return(NULL);            }            default:            {                printf("unexpected signal %d\n", signo);                exit(1);            }        }    }}int main(void){    int         err;    sigset_t    oldmask;    pthread_t   tid;    sigemptyset(&mask);    sigaddset(&mask, SIGINT);    sigaddset(&mask, SIGQUIT);    if ((err = pthread_sigmask(SIG_BLOCK, &mask, &oldmask)) != 0) {        printf("pthread_sigmask(SIG_BLOCK) failed\n");        exit(1);    }    if ((err = pthread_create(&tid, NULL, thr_fn, NULL)) != 0) {        printf("pthread_create failed\n");        exit(1);    }    pthread_mutex_lock(&lock);    while (quitflag == 0) {        pthread_cond_wait(&wait, &lock);    }    pthread_mutex_unlock(&lock);    /* SIGQUIT has been caught and is now blocked, do whatever */    quitflag = 0;    /* reset signal mask which unblocks SIGQUIT */    if (sigprocmask(SIG_SETMASK, &oldmask, NULL) != 0) {        printf("sigprocmask(SIG_SETMASK) failed\n");        exit(1);    }    exit(0);}

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <pthread.h>pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER;pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER;void prepare(void){    printf("preparing locks...\n");    pthread_mutex_lock(&lock1);    pthread_mutex_lock(&lock2);}void parent(void){    printf("parent unlocking locks...\n");    pthread_mutex_unlock(&lock1);    pthread_mutex_unlock(&lock2);}void child(void){    printf("child unlocking locks...\n");    pthread_mutex_unlock(&lock1);    pthread_mutex_unlock(&lock2);}void * thr_fn(void * arg){    printf("thread started...\n");    pause();    return(0);}int main(void){    int        err;    pid_t      pid;    pthread_t  tid;#if defined(BSD) || defined(MACOS)    printf("pthread_atfork is unsupported\n");#else    if ((err = pthread_atfork(prepare, parent, child)) != 0) {        printf("cannot install fork handlers: %s\n", strerror(err));        exit(1);    }    if ((err = pthread_create(&tid, NULL, thr_fn, NULL)) != 0) {        printf("pthread_create failed: %s\n", strerror(err));    }    sleep(2);    printf("parent about to fork ...\n");    if ((pid = fork()) < 0) {        printf("fork failed\n");        exit(1);    }    else if (pid == 0) {        printf("child returned from fork\n");    }    else {        printf("parent returned from fork\n");    }#endif    exit(0);}

#include <unistd.h>#include <time.h>#include <sys/select.h>unsigned int sleep(unsigned int seconds){    int            n;    unsigned       slept;    time_t         start;    time_t         end;    struct timeval tv;    tv.tv_sec = seconds;    tv.tv_usec = 0;    time(&start);    n = select(0, NULL, NULL, NULL, &tv);    if (n == 0) {        return(0);    }    time(&end);    slept = end - start;    if (slept >= seconds) {        return(0);    }    else {        return(seconds - slept);    }}


原创粉丝点击