APUE Learning Example Source Code
Guo Wenxue
2018-11-15 f216a409197724504799ee59720f9ee19e84060c
Update ch3_fork a small bug, and add pthread sample code
1 files modified
5 files added
568 ■■■■■ changed files
ch3_fork/socket_server.c 2 ●●● patch | view | raw | blame | history
ch4_thread/daemon.c 32 ●●●●● patch | view | raw | blame | history
ch4_thread/signal.c 105 ●●●●● patch | view | raw | blame | history
ch4_thread/socket_server_thread.c 203 ●●●●● patch | view | raw | blame | history
ch4_thread/thread.c 103 ●●●●● patch | view | raw | blame | history
ch4_thread/thread_lock.c 123 ●●●●● patch | view | raw | blame | history
ch3_fork/socket_server.c
@@ -142,7 +142,7 @@
            rv=write(clifd, MSG_STR, strlen(MSG_STR));
                   if(rv < 0)
                   {
                       printf("Write to client by sockfd[%d] failure: %s\n", sockfd, strerror(errno));
                       printf("Write to client by sockfd[%d] failure: %s\n", clifd, strerror(errno));
                       close(clifd);
                exit(0);
                   }
ch4_thread/daemon.c
New file
@@ -0,0 +1,32 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <syslog.h>
#include <libgen.h> /* basename() */
int main(int argc, char **argv)
{
    char      *progname = basename(argv[0]);
    if( daemon(0, 0) < 0)
    {
        printf("Program daemon() failure: %s\n", strerror(errno));
        return -1;
    }
    openlog("daemon", LOG_CONS | LOG_PID, 0);
    syslog(LOG_NOTICE,  "Program '%s'start running\n",  progname);
    syslog(LOG_WARNING,  "Program '%s' running with a warnning message\n",  progname );
    syslog(LOG_EMERG,  "Program '%s' running with a emergency message\n",  progname );
    while(1)
    {
         //Do Something here
         ;
    }
    syslog(LOG_NOTICE,  "Program '%s' stop running\n",  progname);
    closelog();
    return 0;
}
ch4_thread/signal.c
New file
@@ -0,0 +1,105 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <execinfo.h>
int         g_sigstop = 0;
void signal_stop(int signum)
{
    if( SIGTERM == signum )
    {
        printf("SIGTERM signal detected\n");
    }
    else if( SIGALRM == signum )
    {
        printf("SIGALRM signal detected\n");
        g_sigstop = 1;
    }
}
void signal_user(int signum)
{
    if(SIGUSR1 == signum)
    {
        printf("SIGUSR1 signal detected\n");
    }
    else if(SIGUSR2 == signum)
    {
        printf("SIGUSR2 signal detected\n");
    }
    g_sigstop = 1;
}
void signal_code(int signum)
{
    if(SIGBUS == signum)
    {
        printf("SIGBUS signal detected\n");
    }
    else if(SIGILL == signum)
    {
        printf("SIGILL signal detected\n");
    }
    else if(SIGSEGV == signum)
    {
        printf("SIGSEGV signal detected\n");
    }
    exit(-1);
}
int main(int argc, char **argv)
{
    char                 *ptr=NULL;
    struct sigaction      sigact, sigign;
    /*+--------------------------------------+
     *| Method1: Use signal() install signal |
     *+--------------------------------------+*/
    signal(SIGTERM, signal_stop);
    signal(SIGALRM, signal_stop);
    signal(SIGBUS, signal_code);
    signal(SIGILL, signal_code);
    signal(SIGSEGV, signal_code);
    /*+-----------------------------------------+
     *| Method2: Use sigaction() install signal |
     *+-----------------------------------------+*/
    /*  Initialize the catch signal structure. */
           sigemptyset(&sigact.sa_mask);
           sigact.sa_flags = 0;
           sigact.sa_handler = signal_user;
    /*  Setup the ignore signal. */
           sigemptyset(&sigign.sa_mask);
           sigign.sa_flags = 0;
           sigign.sa_handler = SIG_IGN;
    sigaction(SIGINT, &sigign, 0); /*  ignore SIGINT signal by CTRL+C */
           sigaction(SIGUSR1,  &sigact, 0); /*  catch SIGUSR1 */
           sigaction(SIGUSR2,  &sigact, 0); /*  catch SIGUSR1 */
    printf("Program start running for 20 seconds...\n");
    alarm(20);
    while( !g_sigstop )
    {
        ;
    }
    printf("Program start stop running...\n");
    printf("Invalid pointer operator will raise SIGSEGV signal\n");
    *ptr = 'h';
    return 0;
}
ch4_thread/socket_server_thread.c
New file
@@ -0,0 +1,203 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <getopt.h>
#include <pthread.h>
#define MSG_STR "Hello LingYun IoT Studio Client\n"
typedef void *(THREAD_BODY) (void *thread_arg);
void *thread_worker(void *ctx);
int thread_start(pthread_t * thread_id, THREAD_BODY * thread_workbody, void *thread_arg);
void print_usage(char *progname)
{
    printf("%s usage: \n", progname);
    printf("-p(--port): sepcify server listen port.\n");
    printf("-h(--Help): print this help information.\n");
    return ;
}
int main(int argc, char **argv)
{
    int                  sockfd = -1;
    int                  rv = -1;
    struct sockaddr_in   servaddr;
    struct sockaddr_in   cliaddr;
    socklen_t            len;
    int                  port = 0;
    int                  clifd;
    int                  ch;
    int                  on = 1;
    pthread_t            tid;
           struct option        opts[] = {
        {"port", required_argument, NULL, 'p'},
        {"help", no_argument, NULL, 'h'},
        {NULL, 0, NULL, 0}
    };
    while( (ch=getopt_long(argc, argv, "p:h", opts, NULL)) != -1 )
    {
        switch(ch)
        {
            case 'p':
                port=atoi(optarg);
                break;
            case 'h':
                print_usage(argv[0]);
                return 0;
        }
    }
    if( !port )
    {
        print_usage(argv[0]);
        return 0;
    }
    sockfd=socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd < 0)
    {
        printf("Create socket failure: %s\n", strerror(errno));
        return -1;
    }
    printf("Create socket[%d] successfully!\n", sockfd);
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family=AF_INET;
    servaddr.sin_port = htons(port);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    //inet_aton("192.168.0.16", &servaddr.sin_addr);
    rv=bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    if(rv < 0)
    {
        printf("Socket[%d] bind on port[%d] failure: %s\n", sockfd, port, strerror(errno));
        return -2;
    }
    listen(sockfd, 13);
    printf("Start to listen on port [%d]\n", port);
    while(1)
    {
        printf("Start accept new client incoming...\n");
        clifd=accept(sockfd, (struct sockaddr *)&cliaddr, &len);
        if(clifd < 0)
        {
            printf("Accept new client failure: %s\n", strerror(errno));
            continue;
        }
        printf("Accept new client[%s:%d] successfully\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
        thread_start(&tid, thread_worker, &clifd);
    }
    close(sockfd);
    return 0;
}
int thread_start(pthread_t * thread_id, THREAD_BODY * thread_workbody, void *thread_arg)
{
    int                 rv = -1;
    pthread_attr_t      thread_attr;
    if( pthread_attr_init(&thread_attr) )
           {
               printf("pthread_attr_init() failure: %s\n", strerror(errno));
        goto CleanUp;
           }
    if( pthread_attr_setstacksize(&thread_attr, 120*1024) )
           {
               printf("pthread_attr_setstacksize() failure: %s\n", strerror(errno));
        goto CleanUp;
    }
    if( pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED) )
           {
               printf("pthread_attr_setdetachstate() failure: %s\n", strerror(errno));
        goto CleanUp;
           }
    /* Create the thread */
           if( pthread_create(thread_id, &thread_attr, thread_workbody, thread_arg) )
    {
        printf("Create thread failure: %s\n", strerror(errno));
               goto CleanUp;
    }
    rv = 0;
CleanUp:
    /* Destroy the  attributes  of  thread */
    pthread_attr_destroy(&thread_attr);
    return rv;
}
void *thread_worker(void *ctx)
{
    int                  clifd;
    int                  rv;
           char                 buf[1024];
    if( !ctx )
    {
        printf("Invalid input arguments in %s()\n", __FUNCTION__);
        pthread_exit(NULL);
    }
    clifd = *(int *)ctx;
    printf("Child thread start to commuicate with socket client...\n");
    while(1)
    {
        memset(buf, 0, sizeof(buf));
               rv=read(clifd, buf, sizeof(buf));
               if( rv < 0)
               {
                   printf("Read data from client sockfd[%d] failure: %s\n", clifd, strerror(errno));
                   close(clifd);
                   pthread_exit(NULL);
               }
        else if( rv == 0)
               {
            printf("Socket[%d] get disconnected\n", clifd);
                   close(clifd);
                   pthread_exit(NULL);
               }
        else if( rv > 0 )
        {
                   printf("Read %d bytes data from Server: %s\n", rv, buf);
               }
        rv=write(clifd, buf, rv);
               if(rv < 0)
               {
                   printf("Write to client by sockfd[%d] failure: %s\n", clifd, strerror(errno));
                   close(clifd);
                   pthread_exit(NULL);
               }
    }
}
ch4_thread/thread.c
New file
@@ -0,0 +1,103 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
void *thread_worker1(void *args);
void *thread_worker2(void *args);
int main(int argc, char **argv)
{
    int              shared_var = 1000;
    pthread_t        tid;
    pthread_attr_t   thread_attr;
    if( pthread_attr_init(&thread_attr) )
    {
        printf("pthread_attr_init() failure: %s\n", strerror(errno));
        return -1;
    }
    if( pthread_attr_setstacksize(&thread_attr, 120*1024) )
    {
        printf("pthread_attr_setstacksize() failure: %s\n", strerror(errno));
        return -1;
    }
    if( pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED) )
    {
        printf("pthread_attr_setdetachstate() failure: %s\n", strerror(errno));
        return -1;
    }
    pthread_create(&tid, &thread_attr, thread_worker1, &shared_var);
    printf("Thread worker1 tid[%ld] created ok\n", tid);
    pthread_create(&tid, NULL, thread_worker2, &shared_var);
    printf("Thread worker2 tid[%ld] created ok\n", tid);
    pthread_attr_destroy(&thread_attr);
    /* Wait until  thread worker2 exit() */
    pthread_join(tid, NULL);
    while(1)
    {
        printf("Main/Control thread shared_var: %d\n", shared_var);
        sleep(10);
    }
}
void *thread_worker1(void *args)
{
    int            *ptr = (int *)args;
    if( !args )
    {
        printf("%s() get invalid arguments\n", __FUNCTION__);
               pthread_exit(NULL);
    }
    printf("Thread workder 1 [%ld] start running...\n", pthread_self());
    while(1)
    {
        printf("+++: %s before shared_var++: %d\n", __FUNCTION__, *ptr);
        *ptr += 1;
        sleep(2);
        printf("+++: %s after sleep shared_var: %d\n", __FUNCTION__, *ptr);
    }
    printf("Thread workder 1 exit...\n");
    return NULL;
}
void *thread_worker2(void *args)
{
    int            *ptr = (int *)args;
    if( !args )
    {
        printf("%s() get invalid arguments\n", __FUNCTION__);
               pthread_exit(NULL);
    }
    printf("Thread workder 2 [%ld] start running...\n", pthread_self());
    while(1)
    {
        printf("---: %s before shared_var++: %d\n", __FUNCTION__, *ptr);
        *ptr += 1;
        sleep(2);
        printf("---: %s after sleep shared_var: %d\n", __FUNCTION__, *ptr);
    }
    printf("Thread workder 2 exit...\n");
    return NULL;
}
ch4_thread/thread_lock.c
New file
@@ -0,0 +1,123 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
void *thread_worker1(void *args);
void *thread_worker2(void *args);
typedef struct worker_ctx_s
{
    int               shared_var;
    pthread_mutex_t   lock;
} worker_ctx_t;
int main(int argc, char **argv)
{
    worker_ctx_t     worker_ctx;
    pthread_t        tid;
    pthread_attr_t   thread_attr;
    worker_ctx.shared_var = 1000;
    pthread_mutex_init(&worker_ctx.lock, NULL);
    if( pthread_attr_init(&thread_attr) )
    {
        printf("pthread_attr_init() failure: %s\n", strerror(errno));
        return -1;
    }
    if( pthread_attr_setstacksize(&thread_attr, 120*1024) )
    {
        printf("pthread_attr_setstacksize() failure: %s\n", strerror(errno));
        return -1;
    }
    if( pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED) )
    {
        printf("pthread_attr_setdetachstate() failure: %s\n", strerror(errno));
        return -1;
    }
    pthread_create(&tid, &thread_attr, thread_worker1, &worker_ctx);
    printf("Thread worker1 tid[%ld] created ok\n", tid);
    pthread_create(&tid, &thread_attr, thread_worker2, &worker_ctx);
    printf("Thread worker2 tid[%ld] created ok\n", tid);
    while(1)
    {
        printf("Main/Control thread shared_var: %d\n", worker_ctx.shared_var);
        sleep(10);
    }
    pthread_mutex_destroy(&worker_ctx.lock);
}
void *thread_worker1(void *args)
{
    worker_ctx_t        *ctx = (worker_ctx_t *)args;
    if( !args )
    {
        printf("%s() get invalid arguments\n", __FUNCTION__);
               pthread_exit(NULL);
    }
    printf("Thread workder 1 [%ld] start running...\n", pthread_self());
    while(1)
    {
        pthread_mutex_lock(&ctx->lock);
        printf("+++: %s before shared_var++: %d\n", __FUNCTION__, ctx->shared_var);
        ctx->shared_var ++;
        sleep(2);
        printf("+++: %s after sleep shared_var: %d\n", __FUNCTION__, ctx->shared_var);
        pthread_mutex_unlock(&ctx->lock);
        sleep(1);
    }
    printf("Thread workder 1 exit...\n");
    return NULL;
}
void *thread_worker2(void *args)
{
    worker_ctx_t        *ctx = (worker_ctx_t *)args;
    if( !args )
    {
        printf("%s() get invalid arguments\n", __FUNCTION__);
               pthread_exit(NULL);
    }
    printf("Thread workder 2 [%ld] start running...\n", pthread_self());
    while(1)
    {
        if(0 != pthread_mutex_trylock(&ctx->lock) )
        {
            continue;
        }
        printf("---: %s before shared_var++: %d\n", __FUNCTION__, ctx->shared_var);
        ctx->shared_var ++;
        sleep(2);
        printf("---: %s after sleep shared_var: %d\n", __FUNCTION__, ctx->shared_var);
        pthread_mutex_unlock(&ctx->lock);
        sleep(1);
    }
    printf("Thread workder 2 exit...\n");
    return NULL;
}