UNP函数笔记十六: 线程

来源:互联网 发布:今日股市数据 编辑:程序博客网 时间:2024/05/16 12:17

第二十六章  线程:

#include <pthread.h>int pthread_create(pthread_t * tid,                    const pthread_attr_t * attr,                    void * (*func)(void *), void * arg);    success return 0, error return Exxx, will not modify errno#include <pthread.h>int pthread_join(pthread_t tid, void ** status);    success return 0, error return Exxx, will not modify errno#include <pthread.h>pthread_t pthread_self(void);#include <pthread.h>int pthread_detach(pthread_t tid);    success return 0, error return Exxx, will not modify errno#include <pthread.h>void pthread_exit(void * status);#include <pthread.h>pthread_once_t once = PTHREAD_ONCE_INIT;int pthread_once(pthread_once_t * onceptr, void (*init)(void));    success return 0, error return Exxx, will not modify errno#include <pthread.h>int pthread_key_create(pthread_key_t * keyptr,                        void (*destructor)(void * value));    success return 0, error return Exxx, will not modify errno#include <pthread.h>void * pthread_getspecific(pthread_key_t key);    return thread private data, no data match with key return NULLint pthread_setspecific(pthread_key_t key, const void * value);    success return 0, error return Exxx, will not modify errno#include <pthread.h>int pthread_mutex_lock(pthread_mutex_t * mptr);    success return 0, error return Exxx, will not modify errnoint pthread_mutex_unlock(pthread_mutex_t * mptr);    success return 0, error return Exxx, will not modify errno#include <pthread.h>int pthread_cond_wait(pthread_cond_t * cptr,                       pthread_mutex_t * mptr);    success return 0, error return Exxx, will not modify errnoint pthread_cond_signal(pthread_cond_t * cptr);    success return 0, error return Exxx, will not modify errnoPTHREAD_COND_INITIALIZER#include <pthread.h>int pthread_cond_broadcast(pthread_cond_t * cptr);    success return 0, error return Exxx, will not modify errnoint pthread_cond_timedwait(pthread_cond_t * cptr,                            pthread_mutex_t * mptr,                            const struct timespec * abstime);    success return 0, error return Exxx, will not modify errno    struct timespec {        time_t    tv_sec;  /* seconds */        long      tv_nsec; /* nanosecods */    };

示例:

#ifndef __WARP_FUNCTION_H__#define __WARP_FUNCTION_H__#include <stdio.h>#include <errno.h>#include <string.h>#include <stdlib.h>#include <pthread.h>#include <sys/socket.h>#ifndef MAXLINE#define MAXLINE 4096#endifvoid err_msg(const char * msg, int error){    printf("%s : %s\n", msg, strerror(error));    exit(1);}int Pthread_create(pthread_t * tid,                    const pthread_attr_t * attr,                    void * (*func)(void *), void * arg){    int error = pthread_create(tid, attr, func, arg);    if (error != 0) {        err_msg("pthread_create error", error);    }    return(error);}int Pthread_join(pthread_t tid, void ** status){    int error = pthread_join(tid, status);    if (error != 0) {        err_msg("pthread_join error", error);    }    return(error);}pthread_t Pthread_self(void){    return(pthread_self());}int Pthread_detach(pthread_t tid){    int error = pthread_detach(tid);    if (error != 0) {        err_msg("pthread_detach error", error);    }    return(error);}void Pthread_exit(void * status){    pthread_exit(status);}int Pthread_once(pthread_once_t * onceptr, void (*init)(void)){    int error = pthread_once(onceptr, init);    if (error != 0) {        err_msg("pthread_once error", error);    }    return(error);}int Pthread_key_create(pthread_key_t * keyptr,                        void (*destructor)(void * value)){    int error = pthread_key_create(keyptr, destructor);    if (error != 0) {        err_msg("pthread_key_create error", error);    }    return(error);}void * Pthread_getspecific(pthread_key_t key){    return((void *)pthread_getspecific(key));}int Pthread_setspecific(pthread_key_t key, const void * value){    int error = pthread_setspecific(key, value);    if (error != 0) {        err_msg("pthread_setspecific error", error);    }    return(error);}int Pthread_mutex_lock(pthread_mutex_t * mptr){    int error = pthread_mutex_lock(mptr);    if (error != 0) {        err_msg("pthread_mutex_lock error", error);    }    return(error);}int Pthread_mutex_unlock(pthread_mutex_t * mptr){    int error = pthread_mutex_unlock(mptr);    if (error != 0) {        err_msg("pthread_mutex_unlock error", error);    }    return(error);}int Pthread_cond_signal(pthread_cond_t * cptr){    int error = pthread_cond_signal(cptr);    if (error != 0) {        err_msg("pthread_cond_signal error", error);    }    return(error);}int Pthread_cond_broadcast(pthread_cond_t * cptr){    int error = pthread_cond_broadcast(cptr);    if (error != 0) {        err_msg("pthread_cond_broadcast error", error);    }    return(error);}int Pthread_cond_wait(pthread_cond_t * cptr,                       pthread_mutex_t * mptr){    int error = pthread_cond_wait(cptr, mptr);    if (error != 0) {        err_msg("pthread_cond_wait error", error);    }    return(error);}int Pthread_cond_timedwait(pthread_cond_t * cptr,                            pthread_mutex_t * mptr,                            const struct timespec * abstime){    int error = pthread_cond_timedwait(cptr, mptr, abstime);    if (error != 0) {        err_msg("pthread_cond_timedwait error", error);    }    return(error);}void * Malloc(size_t size){    void * ptr = malloc(size);    if (ptr == NULL) {        err_msg("malloc error", errno);    }    return(ptr);}void * Calloc(size_t nobj, size_t size){    void * ptr = calloc(nobj, size);    if (ptr == NULL) {        err_msg("calloc error", errno);    }    return(ptr);}int Socket(int family, int type, int protocol){    int sockfd = socket(family, type, protocol);    if (sockfd == -1) {        err_msg("socket error", errno);    }    return(sockfd);}int Connect(int sockfd, const struct sockaddr * servaddr, socklen_t addrlen){    int ret = connect(sockfd, servaddr, addrlen);    if (ret == -1) {        err_msg("connect error", errno);    }    return(ret);}int Bind(int sockfd, const struct sockaddr * myaddr, socklen_t addrlen){    int ret = bind(sockfd, myaddr, addrlen);    if (ret == -1) {        err_msg("bind error", errno);    }    return(ret);}int Listen(int sockfd, int backlog){    int ret = listen(sockfd, backlog);    if (ret == -1) {        err_msg("listen error", errno);    }    return(ret);}int Accept(int sockfd, struct sockaddr * cliaddr, socklen_t * addrlen){    int ret = accept(sockfd, cliaddr, addrlen);    if (ret == -1) {        err_msg("accept error", errno);    }    return(ret);}pid_t Fork(void){    int ret = fork();    if (ret == -1) {        err_msg("fork error", errno);    }    return(ret);}int Close(int sockfd){    int ret = close(sockfd);    if (ret == -1) {        err_msg("close error", errno);    }    return(ret);}int Shutdown(int sockfd, int howto){    int ret = shutdown(sockfd, howto);    if (ret == -1) {        err_msg("shutdown error", errno);    }    return(ret);}int Getsockname(int sockfd, struct sockaddr * localaddr, socklen_t * addrlen){    int ret = getsockname(sockfd, localaddr, addrlen);    if (ret == -1) {        err_msg("getsockname error", errno);    }    return(ret);}int Getpeername(int sockfd, struct sockaddr * peeraddr, socklen_t * addrlen){    int ret = getpeername(sockfd, peeraddr, addrlen);    if (ret == -1) {        err_msg("getpeername error", errno);    }    return(ret);}#endif

#include "warp.h"#include "tcp_connect.h"static int    sockfd;  /* global for both threads to access */static FILE * fp;void * copyto(void * arg){    int   n;    char  sendline[MAXLINE];    while (fgets(sendline, MAXLINE, fp) != NULL) {        n = strlen(sendline);        if (writen(sockfd, sendline, n) != n) {            err_msg("writen error", errno);        }    }    if (ferror(fp)) {        err_msg("fgets error", errno);    }    Shutdown(sockfd, SHUT_WR);  /* EOF on stdin, send FIN */    return(NULL);}void str_cli(FILE * fp_arg, int sockfd_arg){    int        n;    char       recvline[MAXLINE];    pthread_t  tid;    sockfd = sockfd_arg;  /* copy arguments to externals */    fp = fp_arg;    Pthread_create(&tid, NULL, copyto, NULL);    while ((n = readline(sockfd, recvline, MAXLINE)) > 0) {        if (fputs(recvline, stdout) == EOF) {            err_msg("fputs error", errno);        }    }    if (n < 0) {        err_msg("readline error", errno);    }}int main(int argc, char ** argv){    int  sockfd;    if (argc != 3) {        printf("usage: tcpcli <hostname> <service>\n");        exit(1);    }    sockfd = tcp_connect(argv[1], argv[2]);    str_cli(stdin, sockfd);  /* do it all */    exit(0);}
#include "warp.h"void * doit(void *arg)  /* each thread executes this function */{    int  connfd;    connfd = *((int *)arg);    free(arg);    Pthread_detach(Pthread_self());    str_echo(connfd);  /* same function as before */    close(connfd);  /* done with connected socket */    return(NULL);}int main(int argc, char ** argv){    int               listenfd;    int             * iptr;    pthread_t         tid;    socklen_t         addrlen;    socklen_t         len;    struct sockaddr * cliaddr;    if (argc == 2) {        listenfd = tcp_listen(NULL, argv[1], &addrlen);    }    else if (argc == 3) {        listenfd = tcp_listen(argv[1], argv[2], &addrlen);    }    else {        printf("usage: tcpserv01 [ <host> ] <service or port>\n");        exit(1);    }    cliaddr = Malloc(addrlen);    for ( ; ; ) {        len = addrlen;        iptr = Malloc(sizeof(int));        *iptr = Accept(listenfd, cliaddr, &len);        Pthread_create(&tid, NULL, &doit, iptr);    }}

#include "warp.h"static pthread_key_t   rl_key;static pthread_once_t  rl_once = PTHREAD_ONCE_INIT;void readline_destructor(void * ptr){    free(ptr);}void readline_once(void){    Pthread_key_create(&rl_key, readline_destructor);}typedef struct {    int    rl_cnt;           /* initialize to 0 */    char * rl_bufptr;        /* initialize to rl_buf */    char   rl_buf[MAXLINE];} Rline;ssize_t my_read(Rline * tsd, int fd, char * ptr){    if (tsd->rl_cnt <= 0) {again:        if ((tsd->rl_cnt = read(fd, tsd->rl_buf, MAXLINE)) < 0) {            if (errno == EINTR) {                goto again;            }            else {                return(-1);            }        }        else if (tsd->rl_cnt == 0) {            return(0);        }        else {            tsd->rl_bufptr = tsd->rl_buf;        }    }    tsd->rl_cnt--;    *ptr = *tsd->rl_bufptr++;    return(1);}ssize_t readline(int fd, void * vptr, size_t maxlen){    size_t   n;    size_t   rc;    char     c;    char   * ptr;    Rline  * tsd;    Pthread_once(&rl_once, readline_once);    if ((tsd = Pthread_getspecific(rl_key)) == NULL) {        tsd = Calloc(1, sizeof(Rline));  /* init to 0 */        Pthread_setspecific(rl_key, tsd);    }    ptr = vptr;    for (n = 1; n < maxlen; n++) {        if ((rc = my_read(tsd, fd, &c)) == 1) {            *ptr++ = c;            if (c == '\n') {                break;            }        }        else if (rc == 0) {            *ptr = 0;            return(n - 1);  /* EOF, n - 1 bytes read */        }        else {            return(-1);  /* error, errno set by read() */        }    }    *ptr = 0;    return(n);}ssize_t Readline(int fd, void * ptr, size_t maxlen){    ssize_t n = readline(fd, ptr, maxlen);    if (n < 0) {        err_msg("readline error", errno);    }    return(n);}

#include "myio.h"#include "warp.h"#include "tcp_connect.h"#define    MAXFILES    20#define    SERV        "80"   /* port number or service name */#define    F_CONNECTING    1    /* connect() in progress */#define    F_READING       2    /* connect() complete; now reading */#define    F_DONE          4    /* all done */#define    F_JOINED        8    /* main has pthread_join'ed */#define    GET_CMD        "GET %s HTTP/1.0\r\n\r\n"#define    min(a, b)       ((a) < (b) ? (a) : (b))struct file {    char     * f_name;   /* filename */    char     * f_host;   /* hostname or IP address */    int        f_fd;     /* descriptor */    int        f_flags;  /* F_xxx above */    pthread_t  f_tid;    /* thread ID */} file[MAXFILES];int  nconn;int  nfiles;int  nlefttoconn;int  nlefttoread;int              ndone;  /* number of terminated threads */pthread_mutex_t  ndone_mutex = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t   ndone_cond = PTHREAD_COND_INITIALIZER;void home_page(const char * host, const char * fname){    int   fd;    int   n;    char  line[MAXLINE];    fd = tcp_connect(host, SERV);  /* blocking connect() */    n = snprintf(line, sizeof(line), GET_CMD, fname);    if (writen(fd, line, n) != n) {        err_msg("writen error", errno);    }    for ( ; ; ) {        if ((n = read(fd, line, MAXLINE)) < 0) {            err_msg("read error", errno);        }        else if (n == 0) {            break;  /* server closed connection */        }        printf("read %d bytes of home page\n", n);        /* do whatever with data */    }    printf("end-of-file on home page\n");    Close(fd);}void write_get_cmd(struct file * fptr){    int   n;    char  line[MAXLINE];    n = snprintf(line, sizeof(line), GET_CMD, fptr->f_name);    if (writen(fptr->f_fd, line, n) != n) {        err_msg("writen error", errno);    }    printf("wrote %d bytes for %s\n", n, fptr->f_name);    fptr->f_flags = F_READING;  /* clears F_CONNECTING */}void * do_get_read(void * vptr){    int           fd;    int           n;    char          line[MAXLINE];    struct file * fptr;    fptr = (struct file *)vptr;    fd = tcp_connect(fptr->f_host, SERV);    fptr->f_fd = fd;    printf("do_get_read for %s, fd %d, thread %d\n",            fptr->f_name, fd, (int)fptr->f_tid);    write_get_cmd(fptr);  /* write() the GET command */    /* Read server's reply */    for ( ; ; ) {        if ((n = read(fd, line, MAXLINE)) < 0) {            err_msg("read error", errno);        }        else if (n == 0) {            break;  /* server closed connection */        }        printf("read %d bytes from %s\n", n, fptr->f_name);    }    printf("end-of-file on %s\n", fptr->f_name);    Close(fd);    fptr->f_flags = F_DONE;  /* clears F_READING */    Pthread_mutex_lock(&ndone_mutex);    ndone++;    Pthread_cond_signal(&ndone_cond);    Pthread_mutex_unlock(&ndone_mutex);    return(fptr);  /* terminate thread */}int main(int argc, char ** argv){    int           i;    int           maxnconn;    pthread_t     tid;    struct file * fptr;    if (argc < 5) {        printf("usage: web <#conns> <IPaddr> <homepage> file1 ...\n");        exit(1);    }    maxnconn = atoi(argv[1]);    nfiles = min(argc - 4, MAXFILES);    for (i = 0; i < nfiles; i++) {        file[i].f_name = argv[i + 4];        file[i].f_host = argv[2];        file[i].f_flags = 0;    }    printf("nfiles = %d\n", nfiles);    home_page(argv[2], argv[3]);    nlefttoread = nlefttoconn = nfiles;    nconn = 0;    while (nlefttoread > 0) {        while (nconn < maxnconn && nlefttoconn > 0) {            /* find a file to read */            for (i = 0 ; i < nfiles; i++) {                if (file[i].f_flags == 0) {                    break;                }            }            if (i == nfiles) {                printf("nlefttoconn = %d but nothing found\n", nlefttoconn);                exit(1);            }            file[i].f_flags = F_CONNECTING;            Pthread_create(&tid, NULL, &do_get_read, &file[i]);            file[i].f_tid = tid;            nconn++;            nlefttoconn--;        }        /* Wait for thread to terminate */        Pthread_mutex_lock(&ndone_mutex);        while (ndone == 0) {            Pthread_cond_wait(&ndone_cond, &ndone_mutex);        }        for (i = 0; i < nfiles; i++) {            if (file[i].f_flags & F_DONE) {                Pthread_join(file[i].f_tid, (void **) &fptr);                if (&file[i] != fptr) {                    printf("error: file[i] != fptr\n");                    exit(1);                }                fptr->f_flags = F_JOINED;    /* clears F_DONE */                ndone--;                nconn--;                nlefttoread--;                printf("thread %d for %s done\n",                        (int)fptr->f_tid, fptr->f_name);            }        }        Pthread_mutex_unlock(&ndone_mutex);    }    exit(0);}


原创粉丝点击