要求实现一个简单的定时器,该程序要求的输入格式为:

N prompt message

其中N表示时间,prompt message表示提示信息。即过了N秒之后要在终端上显示出提示信息。一共用了三种方式实现:(1)最普通的方式,阻塞I/0+同步。(2)使用进程实现。(3)使用线程实现。

  1. /*alarm.c*/
  2. #include "../error.h"
  3. #include<time.h>
  4. int main(int argc,char *argv[])
  5. {
  6. int seconds;
  7. char line[128];
  8. char message[64];
  9. while(NULL != fgets(line,sizeof(line),stdin))
  10. {
  11. if( 2 > sscanf(line,"%d %64[^\n]",&seconds,message))
  12. fprintf(stderr,"Bad Command\n");
  13. else
  14. {
  15. sleep(seconds);
  16. fprintf(stdout,"%s\n",message);
  17. }
  18. }
  19. return 0;
  20. }

评注:

1.常量和函数比较的时候,将常量放在前面可以防止将==写成=,因为编译器会报错。

2.sscanf为从一个字符缓冲区中格式化读取数据。注意字符缓冲区放在第一个参数位置。使用%N可以控制读取字符的数量,中括号的作用和正则表达式中的作用一样,将不读取的字符排除掉或者仅读取中括号内指定的字符集,成功时,返回读取的参数的个数。

3.使用fgets+sscanf,简化了从命令行中提取参数问题。

3.fgets从指定的文件描述符中读取一行字符串,失败时返回NULL。

4.对于每个函数都添加了判断语句,特别有助于调试。

  1. /*alarm_fork.c*/
  2. #include "../error.h"
  3. #include <sys/types.h>
  4. #include<wait.h>
  5. int main(int argc,char *argv[])
  6. {
  7. pid_t pid;
  8. int seconds;
  9. char line[128];
  10. char message[64];
  11. while(NULL != fgets(line,sizeof(line),stdin))
  12. {
  13. if(2 > sscanf(line,"%d %64[^\n]",&seconds,message))
  14. {
  15. fprintf(stdout,"Bad command.\n");
  16. continue;
  17. }
  18. else
  19. {
  20. pid = fork();
  21. if((pid_t)-1 == pid)
  22. {
  23. error_abort("fork error...");
  24. }
  25. else if((pid_t)0 == pid)
  26. {
  27. sleep(seconds);
  28. fprintf(stdout,"%s\n",message);
  29. exit(0);
  30. }
  31. else
  32. {
  33. do
  34. {
  35. pid = waitpid((pid_t)-1,NULL,WNOHANG);
  36. if((pid_t)-1 == pid)
  37. {
  38. error_abort("waitpid error...");
  39. }
  40. }while((pid_t)0 != pid);
  41. }
  42. }
  43. }
  44. return 0;
  45. }

1.pid_t这个类型在sys/types.h头文件中。

2.比较的时候要进行强制类型转换,比如判断进程id是不是为0,就要使用(pid_t)0 == pid这样的判断语句。

3.waitpid的第一个参数设置为-1,第三个参数设置为WNOHANG,表示非阻塞等待任何一个子进程。如果发现一个子进程返回,立即再判断是否还有其他进程返回。可以迅速的释放不再使用的资源。

  1. /*alarm_thread.c*/
  2. #include "../error.h"
  3. #include <sys/types.h>
  4. #include <pthread.h>
  5. #include <time.h>
  6. typedef struct alarm_tag
  7. {
  8. int seconds;
  9. char message[64];
  10. }alarm_t,*alarm_p;
  11. void * alarm_thread(void * arg)
  12. {
  13. int status;
  14. status = pthread_detach(pthread_self());
  15. if(0 != status)
  16. err_abort("detaching thread failure...",status);
  17. alarm_p alarm = (alarm_p) arg;
  18. sleep(alarm->seconds);
  19. fprintf(stdout,"%s\n",alarm->message);
  20. }
  21. int main(int argc,char *argv[])
  22. {
  23. pthread_t thread;
  24. char line[128];
  25. alarm_p alarm;
  26. int status;
  27. while(NULL != fgets(line,sizeof(line),stdin))
  28. {
  29. alarm = (alarm_p) malloc(sizeof(alarm_t));
  30. if( NULL == alarm)
  31. error_abort("Allocating alarm failure...");
  32. if(2 > sscanf(line,"%d %64[^\n]",&alarm->seconds,alarm->message))
  33. {
  34. fprintf(stdout,"%s\n","Bad command");
  35. free(alarm);
  36. continue;
  37. }
  38. else
  39. {
  40. status = pthread_create(&thread,NULL,alarm_thread,(void *)alarm);
  41. if(0 != status)
  42. err_abort("creating thread failure...",status);
  43. }
  44. }
  45. return 0;
  46. }

1.Pthreads相关的类型,接口原型,常量都在pthread.h这个头文件中,编译的时候要加 -lpthread.

2.由于线程的参数只有一个,所以要将传给线程的所有参数封装到一个结构体中。

使用普通方式,多进程,多线程的比较

alarm一次只能发出一个定时请求。如果发出一个10分钟的请求,那么必须要等十分钟才能发出下一个请求。多进程解决了这个同步问题,但是在一个系统中,一个用户能够启动的进程的数量是非常有限的,多线程受到这个影响要小得多。

多线程的几个好处

(1)发掘多核计算潜力

(2)发掘程序自身的并发性

(3)模块式的编程模型,可以更加清晰的表达不同事件之间的关系

转载于:https://blog.51cto.com/hipercomer/908959

一个定时器的普通实现,多进程实现和多线程实现的对比相关推荐

  1. Android设置多个定时器时只有最后一个定时器有效的问题

    AlarmManager的常用方法有三个: (1)set(int type,long startTime,PendingIntent pi):         该方法用于设置一次性闹钟,第一个参数表示 ...

  2. 适用于WinForm的一个定时器类

    尽管.Net已经提供了3个Timer,我仍然要自己利用BackgroundWorker组件封装这么一个定时器来使用. 主要原因是System.Windows.Forms以及System.Threadi ...

  3. java定时任务中使用多线程_java项目中如何利用多线程实现一个定时器任务

    java项目中如何利用多线程实现一个定时器任务 发布时间:2020-11-10 16:04:03 来源:亿速云 阅读:86 作者:Leah 今天就跟大家聊聊有关java项目中如何利用多线程实现一个定时 ...

  4. 【定时器/中断/PWM】利用一个定时器实现一路PWM波的输出---点亮LED

    ------------------------------------------凑热闹的分割线------------------------------------------------ /* ...

  5. 【数码管/定时器/中断】一个定时器控制数码管显示

    两种方式实现 /*用定时器以间隔500MS在6位数码管上 依次显示0.1.2.3-.C.D.E.F,重复.*/ /*轮流在每一位数码管上显示*/ --------------------------- ...

  6. Java如何简单实现一个定时器

    什么是定时器? 它就像是一个闹钟一样,提醒你在一定时间之后该去做什么~~ 前面在线程池的时候提到过两种可以执行延迟任务的方法 创建一个单线程可以执行延迟任务的线程池,Executors.newSing ...

  7. STM32单片机一个定时器输出不同频率PWM波

      在使用STM32单片机输出PWM波形的时候,通常可以直接使用定时器提供的PWM模式.可以通过自动重装载寄存器(TIMx_ARR)来设置定时器的输出频率,然后通过捕获/ 比较寄存器 1(TIMx_C ...

  8. STM32用一个定时器封装多个定时函数调用

    STM32用一个定时器封装多个定时函数调用 用一个定时器开一个1ms的中断: 头文件宏定义如下: #define BASIC_TIM TIM6 #define BASIC_TIM_APBxClock_ ...

  9. 51单片机实现用一个定时器输出可调PWM

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.为什么要用一个定时器实现? 使用步骤 2.代码思路 3.如何改变输出频率和正脉宽 一.调节正脉宽 二.调节频率 使 ...

  10. 在表格中展示订单的倒计时定时器,用一个定时器显示多个倒计时

    问题背景 项目中有个需求是要展示订单列表中待支付的订单显示倒计时,在订单支付后,或者 超时后刷新列表,更新状态 解决思路 项目使用的vue框架,就要运用vue的数据驱动试图这一特性,所以我们需要添加一 ...

最新文章

  1. android 带边框的圆角按钮
  2. OpenCV在Android设备上运行深度网络
  3. 如何在Elasticsearch中进行深分页
  4. 远程办公第五天,你还在扩容吗?
  5. Linux进程管理+内存管理:进程切换的TLB处理(ASID-address space ID、PCID-process context ID)
  6. DEDE_5.7星星评分插件首发!
  7. 防止浏览器嗅探音视频--blob对象在audio和video标签中的使用
  8. linux沙箱隔离_为容器提供更好的隔离:沙箱容器技术概览
  9. 三极管在ad中的原理图库_Altium Designer原理图元器件库详细说明
  10. Tomcat:The server encountered an internal error () that prevented it from fulfilling this request.
  11. html5标签思维导图,HTML/HTML5 知识点思维导图
  12. 地磅无人值守称重系统怎样实现自动发货的?
  13. 微信锁屏密码怎么设置
  14. 微信小程序app.json全局配置项
  15. Android动画之AnimatorSet联合动画用法
  16. 用三种方式安装Nginx
  17. 设为首页,收藏本站代码
  18. 【洛谷题解】P1255 数楼梯
  19. python爬虫遇到验证码的处理方法(以爬取中国执行信息公开网为例)
  20. Facebook首席产品官和WhatsApp副总裁即将离职

热门文章

  1. ArcGIS栅格数据批量转换格式
  2. 【ArcGIS|空间分析】在范围内平均生成点 | 面要素内均匀且规定个数来均匀生成点
  3. 激光雷达(LiDAR)简介-森林资源调查应用
  4. jQuery-zTree插件使用
  5. laydate组件 无法传值_Vue组件间通信几种方式,你用哪种?【实践】
  6. php mysql 组件_Ubuntu20.04安装apache、mysql、php、phpmyadmin、wordpress(一)
  7. springboot 多线程_从零开始到架构,800页Java+并发+容器+多线程+高并发+Spring+SpringBoot源码...
  8. selenium启动火狐浏览器_selenium之nodejs入门使用
  9. 虚拟服务器怎么搭建php,怎样搭建Apache+MySQL+PHP服务器
  10. mysql safe 模式_MYSQL的安全模式:sql_safe_updates介绍