本次主要和大家分享两个闹钟程序。它们分别是同步版本、多进程版本,之后和大家分享多线程版本。
该程序循环接受用户的输入信息,直到出错或者输入完毕。用户输入的信息第一部分是闹钟等待时间(以秒为单位),第二部分是闹钟时间到达后所显示的信息。
一 同步版本
创建Qt控制台程序,由于闹钟程序是c语言的,需要包含如下2个头文件。第一个是标准io的头文件,第二个是sleep()函数用到的头文件。接下来上码。
#include <QCoreApplication>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int seconds;
char line[128];
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 {
sleep (seconds);
printf ("(%d) %s\n", seconds, message);
}
}
return a.exec();
}
程序过程:
fgets(), c语言函数,程序中是从标准输入流读取并存储到line中,当读取(n-1)个字符、或读取到换行符时,或到达文件末尾时则停止。程序中如果读取结果为NULL,则程序退出。(出错或者到达文件尾部)如果读取长度不大于1,比如直接按下Enter键,则重新循环。
sscanf(), 从字符串中读取与指定格式相符的数据,成功时返回参数数目,失败返回-1。程序中是解析line中的字符串,将秒数解析到seconds中,显示信息解析到message中。集合操作 %64[^\n]——%64表示最大取64个字节,[^\n]匹配非\n的任意字符,贪婪性。即不要换行符,最多读64个字节。
成功解析字符串后,延时、打印信息。
缺点:一次只能处理一个闹钟请求。实际上是把希望用异步方式实现的工作用同步方式实现了。
二 多进程版本
有多种异步实现该程序的方法。其中一种方式是为每个命令使用fork调用生成一个子进程。这样可以随时输入命令行,彼此独立运行,不会阻塞等待。程序难点在于对子进程的资源回收,不做重点说明。
上码:
#include <QCoreApplication>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <wait.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, 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)
printf("faild\n");
if (pid == (pid_t)0) {
sleep (seconds);
printf ("(%d) %s\n", seconds, message);
exit (0);
} else {
do {
pid = waitpid ((pid_t)-1, NULL, WNOHANG);
if (pid == (pid_t)-1)
printf("Wait for child\n");
} while (pid != (pid_t)0);
}
}
}
return a.exec();
}
程序说明:
pid_t 对应头文件#include <sys/types.h>,waitpid函数对应#include <wait.h>头文件。
成功解析输入信息后,创建子进程延时、显示信息。父进程则等待子进程结束并回收资源,通常是调用某个waitpid函数。
WNOHANG属性使父进程不必挂起等待子进程结束。如果有子进程终止,则waitpid ()函数回收子进程资源,如果没有子进程结束,该函数立即返回0。父进程继续回收终止的子进程直到没有子进程终止。
程序运行结果如图: