我们现在编写一个简单的闹铃程序,允许用户输入一个时间,在这个时间过后闹钟显示到达时间的文本消息。
#include "errors.h" #include <stdio.h> int main(int argc, char **argv) { int seconds; char line[128]; char message[128]; while (1) { printf("Alarm> "); if (fgets(line, sizeof(line), stdin) == NULL) exit(0); if (strlen(line) <= 1) continue; if (sscanf(line, "%d %64[^\n]", &seconds, message) < 2) { fprintf(stderr, "Bad command\n"); } else { sleep(seconds); printf("(%d) %s\n", seconds, message); } } return 0; }
这是最简单的不使用多线程的版本,在这个版本中。接收到用户的输入之后,主线程直接休眠相应的时间,在此期间程序无法接收其他任何的事件。
二:多线程版本
#include <sys/types.h> #include <wait.h> #include "errors.h" int main(int argc, char **argv) { char line[128]; int seconds; pid_t pid; char message[64]; while (1) { printf("Alarm> "); if (fgets(line, sizeof(line), stdin) == NULL) exit(0); if (strlen(line) <= 1) continue; if (sscanf(line, "%d %64[^\n]", &seconds, message) < 2) { fprintf(stderr, "Bad Command\n"); } else { pid = fork(); if (pid == (pid_t) -1) //fork()函数失败 errno_abort("Fork"); if (pid == (pid_t) 0) { //In The Child sleep(seconds); printf("(%d) %s\n", seconds, message); exit(0); } else { //In The Parent do { pid = waitpid((pid_t) -1, NULL, WNOHANG); if (pid == (pid_t) -1) errno_abort("Wait for child"); } while (pid != (pid_t) 0); } } } return 0; }
在这个版本里,main函数没有直接调用sleep,而是创建了一个子进程,在子进程中异步地调用sleep函数,父进程则继续接受用户的输入。fork函数的调用,会产生一个子进程,而这个子进程和父进程之间的区别就是这个函数的返回值。在子进程中,fork函数的返回值是0;而在父进程中,fork函数的返回值是子进程的pid;
三:多进程版本
#include <pthread.h> #include "errors.h" typedef struct alarm_tag { int seconds; char message[64]; } alarm_t; void *alarm_thread(void *arg) { int status; alarm_t *alarm = (alarm_t*) arg; status = pthread_detach(pthread_self()); if (status != 0) err_abort(status, "Detach thread"); sleep(alarm->seconds); printf("(%d) %s\n", alarm->seconds, alarm->message); free(alarm); return NULL; } int main(int argc, char **argv) { int status; char line[128]; alarm_t *alarm; pthread_t thread; while (1) { printf("Alarm> "); if (fgets(line, sizeof(line), stdin) == NULL) exit(0); if (strlen(line) <= 1 ) continue; alarm = (alarm_t*)malloc(sizeof(alarm_t)); if (alarm == NULL) errno_abort("Allocate alarm"); if (sscanf(line, "%d %64[^\n]", &alarm->seconds, alarm->message) < 2) { fprintf(stderr, "Bad Command\n"); free(alarm); } else { status = pthread_create(&thread, NULL, alarm_thread, alarm); if (status != 0) err_abort(status, "Create alarm thread"); } } }
多线程的版本和多进程版本的设计想法是一样的,接收到一个用户的输入之后。马上创建一个新的线程,让线程异步地休眠,返回提示信息。主线程依旧处理用户的输入,创建线程。
但是我们可能要为每一个闹钟实例创建一个线程。之后我们可能会给出新的版本专门负责等待闹钟的终止。
errors.h 文件
#ifndef ERRORS_H_ #define ERRORS_H_ #include <unistd.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef DEBUG # define DPRINTF(arg) printf arg #else # define DPRINTF(arg) #endif #define err_abort(code, text) do { \ fprintf( stderr, "%s at \"%s\":%d: %s\n", \ text, __FILE__, __LINE__, strerror(code)); \ abort(); \ } while (0) #define errno_abort(text) do { \ fprintf( stderr, "%s at \"%s\":%d: %s\n", \ text, __FILE__, __LINE__, strerror(errno)); \ abort(); \ } while (0) #endif /* ERRORS_H_ */
Programming With POSIX Threads 读书笔记(一)http://blog.csdn.net/hyzhou33550336/article/details/16890691
Programming With POSIX Threads 读书笔记(二)http://blog.csdn.net/hyzhou33550336/article/details/16890959
Programming With POSIX Threads 读书笔记(三)http://blog.csdn.net/hyzhou33550336/article/details/16899433