APUE函数笔记十: 线程控制

58 篇文章 0 订阅
49 篇文章 0 订阅

第十二章  线程控制:

#include <pthread.h>
int pthread_attr_init(pthread_attr_t * attr);
    if success return 0, else return error-no, will not modify errno
int 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 errno
int 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 errno
int 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 errno
int 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 errno
int 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 default
int 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 errno
int 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 errno
int 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 errno
int 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 errno
int 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 errno
int 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 errno
int 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 errno
int 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-zero
void 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 feof
int getc_unlock(FILE * fp);
    if error or end-of-file return EOF, if EOF check it with ferror or feof
int putchar_unlock(int c);
    if success return c, else return EOF
int 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 NULL
int 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);
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值