posix thread概述(示例代码)
一个简单的alarm实例
errors.h头文件
1 #ifndef __ERRORS_H 2 #define __ERORRS_H 3 4 #include<stdio.h> 5 #include<unistd.h> 6 #include<errno.h> 7 #include<stdlib.h> 8 #include<string.h> 9 10 #ifdef DEBUG 11 #define DPRINTF(arg) printf arg 12 #else 13 #define DPRINTF(arg) 14 #endif 15 16 #define err_abort(code, text) do { \ 17 fprintf(stderr, "%s at \"%s\":%d: %s\n", \ 18 text, __FILE__, __LINE__, strerror(code)); \ 19 abort(); \ 20 } while(0) 21 22 #define errno_abort(text) do { \ 23 fprintf(stderr, "%s at \"%s\":%d: %s\n", \ 24 text, __FILE__, __LINE__, strerror(errno));\ 25 abort();\ 26 }while(0) 27 28 #endif
普通实现:alarm.c
1 #include"errors.h" 2 3 /* alarm的普通实现 */ 4 int main(int argc, char* argv[]) 5 { 6 int seconds; 7 char line[128]; 8 char message[64]; 9 10 while(1) 11 { 12 printf("Alarm> "); 13 if(fgets(line, sizeof(line), stdin) == NULL ) exit(0); 14 if(strlen(line) <= 1 ) continue; 15 if(sscanf(line, "%d %64[^\n]", &seconds, message) < 2 ) 16 fprintf(stderr, "Bad command\n"); 17 else 18 { 19 sleep(seconds); 20 printf("(%d) %s\n", seconds, message); 21 } 22 23 } 24 }
多进程实现:alarm_fork.c
1 #include "errors.h" 2 #include<sys/types.h> 3 #include<wait.h> 4 5 /* alarm的多进程实现 */ 6 int main(int argc, char* argv[]) 7 { 8 int status; 9 char line[128]; 10 int seconds; 11 pid_t pid; 12 char message[64]; 13 14 while(1) 15 { 16 printf("Alarm> "); 17 if(fgets(line, sizeof(line), stdin) == NULL ) exit(0); 18 if(strlen(line) <= 1) continue; 19 if(sscanf(line, "%d %64[^\n]", 20 &seconds, message) < 2) 21 { 22 fprintf(stderr, "Bad command\n"); 23 } 24 else 25 { 26 pid = fork(); 27 if(pid == (pid_t)-1) 28 errno_abort("fork"); 29 if(pid == (pid_t)0) 30 { 31 sleep(seconds); 32 printf("(%d) %s\n", seconds, message); 33 exit(0); 34 } 35 else 36 { 37 do 38 { 39 pid = waitpid((pid_t)-1, NULL, WNOHANG); 40 if(pid == (pid_t)-1) 41 errno_abort("wait child"); 42 }while(pid != (pid_t)0); 43 } 44 } 45 } 46 }
多线程实现:alarm_thread.c
1 #include<pthread.h> 2 #include "errors.h" 3 4 /* alarm的多线程实现 */ 5 6 typedef struct alarm_tag { 7 int seconds; 8 char message[64]; 9 } alarm_t; 10 11 void * alarm_thread(void *arg) 12 { 13 alarm_t *alarm = (alarm_t*)arg; 14 int status; 15 16 status = pthread_detach(pthread_self()); 17 if( status != 0 ) 18 err_abort(status, "pthread_detach"); 19 sleep(alarm->seconds); 20 printf("(%d) %s\n", alarm->seconds, alarm->message); 21 free(alarm); 22 return NULL; 23 } 24 25 int main(int argc, char* argv[]) 26 { 27 int status; 28 char line[128]; 29 alarm_t *alarm; 30 pthread_t thread; 31 32 while(1) 33 { 34 printf("Alarm> "); 35 if(fgets(line, sizeof(line), stdin ) == NULL ) exit(0); 36 if(strlen(line) <= 1) continue; 37 alarm = (alarm_t*)malloc(sizeof(alarm_t)); 38 if( alarm == NULL ) 39 errno_abort("malloc"); 40 if( sscanf(line, "%d %64[^\n]", 41 &alarm->seconds, alarm->message) < 2) 42 { 43 fprintf(stderr, "Bad command\n"); 44 free(alarm); 45 } 46 else 47 { 48 status = pthread_create(&thread, NULL, alarm_thread, alarm); 49 if( status != 0) 50 err_abort(status, "pthread_creat"); 51 } 52 } 53 }
在以上alarm_thread.c代码执行时候,发现如果输入正好是128-1的倍数,将会出现Bad Command的提示。
追究下原因,原来是fgets导致:
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or
a newline. If a newline is read, it is stored into the buffer. A terminating null byte ('\0') is stored after the last character in the buffer.
1 #include<stdio.h> 2 #include<unistd.h> 3 #include<error.h> 4 #include<stdlib.h> 5 6 void main(void) 7 { 8 char line[4]; 9 char* message; 10 11 while(1) 12 { 13 printf("INPUT> "); 14 if(fgets(line, sizeof(line), stdin ) == NULL ) exit(0); 15 message = (char*)malloc(8); 16 if( sscanf(line, "%2[^\n]", 17 message) < 1) 18 { 19 fprintf(stderr, "sscanf error.\n"); 20 } 21 else 22 { 23 printf("message: %s\n", message); 24 } 25 free(message); 26 } 27 } 28 29 /* 30 *root@jdu-virtual-machine:~# ./a.out 31 *INPUT> aaa 32 *message: aa 33 *sscanf error. 34 *INPUT> INPUT> ^C 35 */
Breakpoint 1 at 0x4007ca: file test.c, line 15. (gdb) r Starting program: /root/a.out INPUT> aaa Breakpoint 1, main () at test.c:15 15 message = (char*)malloc(8); (gdb) p line $1 = "aaa" (gdb) n 16 if( sscanf(line, "%2[^\n]", (gdb) 23 printf("message: %s\n", message); (gdb) p message $2 = 0x602010 "aa" (gdb) n message: aa 25 free(message); (gdb) 26 } (gdb) 13 printf("INPUT> "); (gdb) 14 if(fgets(line, sizeof(line), stdin ) == NULL ) exit(0); (gdb) Breakpoint 1, main () at test.c:15 15 message = (char*)malloc(8); (gdb) p line $3 = "\n\000a" (gdb) n 16 if( sscanf(line, "%2[^\n]", (gdb) 19 fprintf(stderr, "sscanf error.\n"); (gdb) sscanf error. 25 free(message); (gdb)