要求实现一个简单的定时器,该程序要求的输入格式为:
N prompt message
其中N表示时间,prompt message表示提示信息。即过了N秒之后要在终端上显示出提示信息。一共用了三种方式实现:(1)最普通的方式,阻塞I/0+同步。(2)使用进程实现。(3)使用线程实现。
-
-
- #include "../error.h"
-
- #include<time.h>
-
- int main(int argc,char *argv[])
-
- {
-
- int seconds;
-
- char line[128];
-
- char message[64];
-
- while(NULL != fgets(line,sizeof(line),stdin))
-
- {
-
- if( 2 > sscanf(line,"%d %64[^\n]",&seconds,message))
-
- fprintf(stderr,"Bad Command\n");
-
- else
-
- {
-
- sleep(seconds);
-
- fprintf(stdout,"%s\n",message);
-
- }
-
- }
-
- return 0;
-
- }
评注:
1.常量和函数比较的时候,将常量放在前面可以防止将==写成=,因为编译器会报错。
2.sscanf为从一个字符缓冲区中格式化读取数据。注意字符缓冲区放在第一个参数位置。使用%N可以控制读取字符的数量,中括号的作用和正则表达式中的作用一样,将不读取的字符排除掉或者仅读取中括号内指定的字符集,成功时,返回读取的参数的个数。
3.使用fgets+sscanf,简化了从命令行中提取参数问题。
3.fgets从指定的文件描述符中读取一行字符串,失败时返回NULL。
4.对于每个函数都添加了判断语句,特别有助于调试。
-
-
- #include "../error.h"
-
- #include <sys/types.h>
-
- #include<wait.h>
-
-
-
- int main(int argc,char *argv[])
-
- {
-
- pid_t pid;
-
- int seconds;
-
- char line[128];
-
- char message[64];
-
- while(NULL != fgets(line,sizeof(line),stdin))
-
- {
-
- if(2 > sscanf(line,"%d %64[^\n]",&seconds,message))
-
- {
-
- fprintf(stdout,"Bad command.\n");
-
- continue;
-
- }
-
- else
-
- {
-
- pid = fork();
-
- if((pid_t)-1 == pid)
-
- {
-
- error_abort("fork error...");
-
- }
-
- else if((pid_t)0 == pid)
-
- {
-
- sleep(seconds);
-
- fprintf(stdout,"%s\n",message);
-
- exit(0);
-
- }
-
- else
-
- {
-
- do
-
- {
-
- pid = waitpid((pid_t)-1,NULL,WNOHANG);
-
- if((pid_t)-1 == pid)
-
- {
-
- error_abort("waitpid error...");
-
- }
-
- }while((pid_t)0 != pid);
-
-
-
- }
-
- }
-
- }
-
- return 0;
-
- }
1.pid_t这个类型在sys/types.h头文件中。
2.比较的时候要进行强制类型转换,比如判断进程id是不是为0,就要使用(pid_t)0 == pid这样的判断语句。
3.waitpid的第一个参数设置为-1,第三个参数设置为WNOHANG,表示非阻塞等待任何一个子进程。如果发现一个子进程返回,立即再判断是否还有其他进程返回。可以迅速的释放不再使用的资源。
-
-
- #include "../error.h"
-
- #include <sys/types.h>
-
- #include <pthread.h>
-
- #include <time.h>
-
-
-
- typedef struct alarm_tag
-
- {
-
- int seconds;
-
- char message[64];
-
- }alarm_t,*alarm_p;
-
-
-
- void * alarm_thread(void * arg)
-
- {
-
- int status;
-
- status = pthread_detach(pthread_self());
-
- if(0 != status)
-
- err_abort("detaching thread failure...",status);
-
- alarm_p alarm = (alarm_p) arg;
-
- sleep(alarm->seconds);
-
- fprintf(stdout,"%s\n",alarm->message);
-
- }
-
-
-
- int main(int argc,char *argv[])
-
- {
-
- pthread_t thread;
-
- char line[128];
-
- alarm_p alarm;
-
- int status;
-
- while(NULL != fgets(line,sizeof(line),stdin))
-
- {
-
- alarm = (alarm_p) malloc(sizeof(alarm_t));
-
- if( NULL == alarm)
-
- error_abort("Allocating alarm failure...");
-
- if(2 > sscanf(line,"%d %64[^\n]",&alarm->seconds,alarm->message))
-
- {
-
- fprintf(stdout,"%s\n","Bad command");
-
- free(alarm);
-
- continue;
-
- }
-
- else
-
- {
-
- status = pthread_create(&thread,NULL,alarm_thread,(void *)alarm);
-
- if(0 != status)
-
- err_abort("creating thread failure...",status);
-
- }
-
- }
-
- return 0;
-
- }
1.Pthreads相关的类型,接口原型,常量都在pthread.h这个头文件中,编译的时候要加 -lpthread.
2.由于线程的参数只有一个,所以要将传给线程的所有参数封装到一个结构体中。
使用普通方式,多进程,多线程的比较
alarm一次只能发出一个定时请求。如果发出一个10分钟的请求,那么必须要等十分钟才能发出下一个请求。多进程解决了这个同步问题,但是在一个系统中,一个用户能够启动的进程的数量是非常有限的,多线程受到这个影响要小得多。
多线程的几个好处
(1)发掘多核计算潜力
(2)发掘程序自身的并发性
(3)模块式的编程模型,可以更加清晰的表达不同事件之间的关系
本文转自hipercomer 51CTO博客,原文链接:http://blog.51cto.com/hipercomer/908959