From f216a409197724504799ee59720f9ee19e84060c Mon Sep 17 00:00:00 2001 From: Guo Wenxue <guowenxue@gmail.com> Date: Thu, 15 Nov 2018 13:32:48 +0800 Subject: [PATCH] Update ch3_fork a small bug, and add pthread sample code --- ch4_thread/daemon.c | 32 +++ ch4_thread/thread.c | 103 ++++++++++ ch4_thread/socket_server_thread.c | 203 ++++++++++++++++++++ ch3_fork/socket_server.c | 2 ch4_thread/thread_lock.c | 123 ++++++++++++ ch4_thread/signal.c | 105 ++++++++++ 6 files changed, 567 insertions(+), 1 deletions(-) diff --git a/ch3_fork/socket_server.c b/ch3_fork/socket_server.c index 875386c..3780019 100644 --- a/ch3_fork/socket_server.c +++ b/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); } diff --git a/ch4_thread/daemon.c b/ch4_thread/daemon.c new file mode 100644 index 0000000..1a03c09 --- /dev/null +++ b/ch4_thread/daemon.c @@ -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; +} diff --git a/ch4_thread/signal.c b/ch4_thread/signal.c new file mode 100644 index 0000000..37bddba --- /dev/null +++ b/ch4_thread/signal.c @@ -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; +} diff --git a/ch4_thread/socket_server_thread.c b/ch4_thread/socket_server_thread.c new file mode 100644 index 0000000..7b194af --- /dev/null +++ b/ch4_thread/socket_server_thread.c @@ -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); + } + } +} + diff --git a/ch4_thread/thread.c b/ch4_thread/thread.c new file mode 100644 index 0000000..2e5b8fa --- /dev/null +++ b/ch4_thread/thread.c @@ -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; +} diff --git a/ch4_thread/thread_lock.c b/ch4_thread/thread_lock.c new file mode 100644 index 0000000..b04f3d5 --- /dev/null +++ b/ch4_thread/thread_lock.c @@ -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; +} -- Gitblit v1.9.1