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

简介:

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

N prompt message

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

 

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

评注:

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

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

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

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

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

 
  1. /*alarm_fork.c*/ 
  2.  
  3. #include "../error.h" 
  4.  
  5. #include <sys/types.h> 
  6.  
  7. #include<wait.h> 
  8.  
  9.   
  10.  
  11. int main(int argc,char *argv[]) 
  12.  
  13.  
  14.         pid_t pid; 
  15.  
  16.         int seconds; 
  17.  
  18.         char line[128]; 
  19.  
  20.         char message[64]; 
  21.  
  22.         while(NULL != fgets(line,sizeof(line),stdin)) 
  23.  
  24.         { 
  25.  
  26.                 if(2 > sscanf(line,"%d %64[^\n]",&seconds,message)) 
  27.  
  28.                 { 
  29.  
  30.                         fprintf(stdout,"Bad command.\n"); 
  31.  
  32.                         continue
  33.  
  34.                 } 
  35.  
  36.                 else 
  37.  
  38.                 { 
  39.  
  40.                         pid = fork(); 
  41.  
  42.                         if((pid_t)-1 == pid) 
  43.  
  44.                         { 
  45.  
  46.                                 error_abort("fork error..."); 
  47.  
  48.                         } 
  49.  
  50.                         else if((pid_t)0 == pid) 
  51.  
  52.                         { 
  53.  
  54.                                 sleep(seconds); 
  55.  
  56.                                 fprintf(stdout,"%s\n",message); 
  57.  
  58.                                 exit(0); 
  59.  
  60.                         } 
  61.  
  62.                         else 
  63.  
  64.                         { 
  65.  
  66.                                 do 
  67.  
  68.                                 { 
  69.  
  70.                                         pid = waitpid((pid_t)-1,NULL,WNOHANG); 
  71.  
  72.                                         if((pid_t)-1 == pid) 
  73.  
  74.                                         { 
  75.  
  76.                                                 error_abort("waitpid error..."); 
  77.  
  78.                                         } 
  79.  
  80.                                 }while((pid_t)0 != pid); 
  81.  
  82.   
  83.  
  84.                         } 
  85.  
  86.                 } 
  87.  
  88.         } 
  89.  
  90.         return 0; 
  91.  

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

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

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

 

 
  1. /*alarm_thread.c*/ 
  2.  
  3. #include "../error.h" 
  4.  
  5. #include <sys/types.h> 
  6.  
  7. #include <pthread.h> 
  8.  
  9. #include <time.h> 
  10.  
  11.   
  12.  
  13. typedef struct alarm_tag 
  14.  
  15.  
  16.         int seconds; 
  17.  
  18.         char message[64]; 
  19.  
  20. }alarm_t,*alarm_p; 
  21.  
  22.   
  23.  
  24. void * alarm_thread(void * arg) 
  25.  
  26.  
  27.         int status; 
  28.  
  29.         status = pthread_detach(pthread_self()); 
  30.  
  31.         if(0 != status) 
  32.  
  33.                 err_abort("detaching thread failure...",status); 
  34.  
  35.         alarm_p alarm = (alarm_p) arg; 
  36.  
  37.         sleep(alarm->seconds); 
  38.  
  39.         fprintf(stdout,"%s\n",alarm->message); 
  40.  
  41.  
  42.   
  43.  
  44. int main(int argc,char *argv[]) 
  45.  
  46.  
  47.         pthread_t thread
  48.  
  49.         char line[128]; 
  50.  
  51.         alarm_p alarm; 
  52.  
  53.         int status; 
  54.  
  55.         while(NULL != fgets(line,sizeof(line),stdin)) 
  56.  
  57.         { 
  58.  
  59.                 alarm = (alarm_p) malloc(sizeof(alarm_t)); 
  60.  
  61.                 if( NULL == alarm) 
  62.  
  63.                         error_abort("Allocating alarm failure..."); 
  64.  
  65.                 if(2 > sscanf(line,"%d %64[^\n]",&alarm->seconds,alarm->message)) 
  66.  
  67.                 { 
  68.  
  69.                         fprintf(stdout,"%s\n","Bad command"); 
  70.  
  71.                         free(alarm); 
  72.  
  73.                         continue
  74.  
  75.                 } 
  76.  
  77.                 else 
  78.  
  79.                 { 
  80.  
  81.                         status = pthread_create(&thread,NULL,alarm_thread,(void *)alarm); 
  82.  
  83.                         if(0 != status) 
  84.  
  85.                                 err_abort("creating thread failure...",status); 
  86.  
  87.                 } 
  88.  
  89.         } 
  90.  
  91.         return 0; 
  92.  

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

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

 

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

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

 

多线程的几个好处

1)发掘多核计算潜力

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

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



本文转自hipercomer 51CTO博客,原文链接:http://blog.51cto.com/hipercomer/908959

相关文章
|
5天前
|
安全 Java 数据处理
Python网络编程基础(Socket编程)多线程/多进程服务器编程
【4月更文挑战第11天】在网络编程中,随着客户端数量的增加,服务器的处理能力成为了一个重要的考量因素。为了处理多个客户端的并发请求,我们通常需要采用多线程或多进程的方式。在本章中,我们将探讨多线程/多进程服务器编程的概念,并通过一个多线程服务器的示例来演示其实现。
|
21天前
|
消息中间件 安全 Linux
线程同步与IPC:单进程多线程环境下的选择与权衡
线程同步与IPC:单进程多线程环境下的选择与权衡
57 0
|
22天前
|
消息中间件 存储 算法
【软件设计师备考 专题 】操作系统的内核(中断控制)、进程、线程概念
【软件设计师备考 专题 】操作系统的内核(中断控制)、进程、线程概念
66 0
|
23天前
|
安全 Python
Python中的并发编程:多线程与多进程技术探究
本文将深入探讨Python中的并发编程技术,重点介绍多线程和多进程两种并发处理方式的原理、应用场景及优缺点,并结合实例分析如何在Python中实现并发编程,以提高程序的性能和效率。
|
22天前
|
消息中间件 Linux 调度
【Linux 进程/线程状态 】深入理解Linux C++中的进程/线程状态:阻塞,休眠,僵死
【Linux 进程/线程状态 】深入理解Linux C++中的进程/线程状态:阻塞,休眠,僵死
62 0
|
14天前
|
安全 Linux API
Android进程与线程
Android进程与线程
18 0
|
21天前
|
存储 算法 Linux
【Linux 系统标准 进程资源】Linux 创建一个最基本的进程所需的资源分析,以及线程资源与之的差异
【Linux 系统标准 进程资源】Linux 创建一个最基本的进程所需的资源分析,以及线程资源与之的差异
24 0
|
22天前
|
并行计算 Python
Python中的并发编程:多线程与多进程的比较
在Python编程中,实现并发操作是提升程序性能的重要手段之一。本文将探讨Python中的多线程与多进程两种并发编程方式的优劣及适用场景,帮助读者更好地选择合适的方法来提高程序运行效率。
|
26天前
|
消息中间件 存储 算法
【C/C++ 泡沫精选面试题04】在实际项目中,多进程和多线程如何选择?
【C/C++ 泡沫精选面试题04】在实际项目中,多进程和多线程如何选择?
41 1
|
27天前
|
并行计算 负载均衡
多线程和多进程优缺点对比。
多线程和多进程优缺点对比。
13 1